重载参数和返回类型的函数

时间:2016-05-16 19:25:41

标签: c++ templates overloading

我知道使用结构进行返回类型重载的技巧:

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...); }
}

如您所见,我遇到了模板不能延伸到其他结构的问题。有没有办法在整个结构上扩展构造函数模板来解决这个特殊问题?或者是否有其他方法可以在保持参数和参数类型重载的同时归档返回类型是否可以超载?

1 个答案:

答案 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();
}