2016-05-16 131 views
1

我知道使用结构为返回类型重载的把戏:重载函数

struct function { 
    operator typeA() { return overloadForTypeA(); } 
    operator typeB() { return overloadForTypeB(); } 
} 

问题是,这种禁止参数和参数类型的重载。所以我一直在试图扩展使用模板这个概念:

struct function { 
    //template on the constructor so types are inffered from arguments 
    template<typename... Args> 
    funct(Args... arguments) { myArguments = arguments; } 

    //intermediate storeage of arguments, problem is the template doesn't extend to here 
    Args myArguments; 

    //overloads for return type int 
    int overloadForInt(char* chr) { return 20; } 
    int overloadForInt(int i) { return 4; } 

    //overloads for return type char 
    char overloadForChar(char* chr) { return 'c'; } 
    char overloadForChar(int i) { return 'i'; } 

    //implcit cast operators to archive return type overloading 
    operator int() { return overloadForInt(myArguments...); } //if myArguments doesn't match any overload of overloadForInt compile error should happen 
    operator char() { return overloadForChar(myArguments...); } 
} 

正如你看到的,我跑成的模板没有延伸到stuct休息的问题。有没有办法在整个结构体上扩展构造函数模板来解决这个特殊问题?还是有另一种方法来归档返回类型可重写,同时保持参数和参数类型重载?

+2

请问您能解释一下您的意思吗?请禁用参数和参数类型重载? – linuxfever

+0

使这个类本身成为一个模板,它需要'Args ...'(或任何你想要的名字)。 – 0x499602D2

+0

通过“禁用参数...”我的意思是你不能传入任何参数,因为隐式转换不会带任何参数。另外,我不能将结构本身作为模板,因为参数的类型不会从构造函数中获取,所以不是“函数(参数)”,而是“函数<参数类型>(参数)” 。这破坏了与普通函数具有相同语法的目的。 (然后最好只使用一个虚拟指针) –

回答

1

隐式转换运算符可能会用多于参数的方式调用您的overloadForXXX,这会导致编译错误。在下面,我将假设你只是想在调用你在构造函数中传递的每个参数的重载。请注意使用Boost Fusion库。这个想法是让你的函数类成为一个类模板,然后使用一个辅助函数来创建这个类,它将推断你的参数类型。

#include <boost/fusion/adapted/std_tuple.hpp> 
#include <boost/fusion/include/for_each.hpp> 
#include <iostream> 



template <class... Args> 
class function { 

    // using a tuple to store the arguments 
    std::tuple<Args...> m_args; 

public: 
    function(Args... args) 
: m_args(std::forward<Args>(args)...){} 

private: 
    struct call_for_int { 

    void overload(char* chr) { 
     std::cout << "Called Int overload with char" << std::endl; 
    } 

    void overload(int chr) { 
     std::cout << "Called Int overload with int" << std::endl; 
    } 

    template <class T> 
    void operator()(T&& t) { 
     overload(std::forward<T>(t)); 
    } 
    }; 

    struct call_for_char { 

    void overload(char* chr) { 
     std::cout << "Called Char overload with char" << std::endl; 
    } 

    void overload(int chr) { 
     std::cout << "Called Char overload with int" << std::endl; 
    } 

    template <class T> 
    void operator()(T&& t) { 
     overload(std::forward<T>(t)); 
    } 
    }; 

public: 
    // use this to call the char overloads 
    void call_char() { 
    auto fun = call_for_char(); 
    boost::fusion::for_each(m_args, std::ref(fun)); 
    } 

    // use this to call the int overloads 
    void call_int() { 
    auto fun = call_for_int(); 
    boost::fusion::for_each(m_args, std::ref(fun)); 
    } 
}; 

// helper function to infer the passed arguments 
template <class... Args> 
auto make_function(Args&&... args) { 
    return function<Args...>(std::forward<Args>(args)...); 
} 

int main() { 
    auto f = make_function(4, 2, 42); 
    f.call_char(); 
    f.call_int(); 
} 
+0

谢谢!我永远不会想出一个辅助函数来引发争论。 –

+0

很高兴能帮到你! – linuxfever