在参数和 return 类型上重载函数

Overloading functions both on parameter and return types

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

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

如您所见,我 运行 遇到了模板未扩展到结构其余部分的问题。有没有办法在整个结构上扩展构造函数模板来解决这个特定问题?或者是否有另一种方法可以在保持参数和参数类型重载的同时存档 return 类型可重载?

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

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