假设我有一些任意复杂的重载函数:
template <class T> void foo(T&& );
template <class T> void foo(T* );
void foo(int );
我想知道,对于给定的表达式, foo()
被调用。例如,给定一些宏WHICH_OVERLOAD
:
using T = WHICH_OVERLOAD(foo, 0); // T is void(*)(int);
using U = WHICH_OVERLOAD(foo, "hello"); // U is void(*)(const char*);
// etc.
我不知道我会在哪里使用这样的东西 - 我只是好奇它是否可能。
答案 0 :(得分:1)
#include <string>
#include <vector>
#include <iostream>
//template <class T> T foo(T ) { std::cout << "template" << std::endl; return {}; };
std::string foo(std::string) { std::cout << "string" << std::endl; return {}; };
std::vector<int> foo(std::vector<int>) { std::cout << "vector<int>" << std::endl; return {}; };
char foo(char) { std::cout << "char" << std::endl; return {}; };
template<typename T>
struct Temp
{
using type = T (*) (T);
};
#define GET_OVERLOAD(func,param) static_cast<Temp<decltype(foo(param))>::type>(func);
int main(void)
{
auto fPtr1 = GET_OVERLOAD(foo, 0);
fPtr1({});
auto fPtr2 = GET_OVERLOAD(foo, std::string{"hello"});
fPtr2({});
auto fPtr3 = GET_OVERLOAD(foo, std::initializer_list<char>{});
fPtr3({});
auto fPtr4 = GET_OVERLOAD(foo, std::vector<int>{});
fPtr4({});
auto fPtr5 = GET_OVERLOAD(foo, std::initializer_list<int>{});
fPtr5({});
return 0;
}
输出结果为:
char
string
string
vector<int>
vector<int>
答案 1 :(得分:0)
我可能与你的想法相去甚远,但我花了很多时间在这上面,并且值得添加一个答案(也许是完全错误的答案):
#include<type_traits>
#include<utility>
template <class T> void foo(T&&);
template <class T> void foo(T*);
void foo(int);
template<int N>
struct choice: choice<N+1> { };
template<>
struct choice<3> { };
struct find {
template<typename A>
static constexpr
auto which(A &&a) {
return which(choice<0>{}, std::forward<A>(a));
}
private:
template<typename A>
static constexpr
auto which(choice<2>, A &&) {
// do whatever you want
// here you know what's the invoked function
// it's template<typename T> void foo(T &&)
// I'm returning its type to static_assert it
return &static_cast<void(&)(A&&)>(foo);
}
template<typename A>
static constexpr
auto which(choice<1>, A *) {
// do whatever you want
// here you know what's the invoked function
// it's template<typename T> void foo(T *)
// I'm returning its type to static_assert it
return &static_cast<void(&)(A*)>(foo);
}
template<typename A>
static constexpr
auto
which(choice<0>, A a)
-> std::enable_if_t<not std::is_same<decltype(&static_cast<void(&)(A)>(foo)), decltype(which(choice<1>{}, std::forward<A>(a)))>::value, decltype(&static_cast<void(&)(A)>(foo))>
{
// do whatever you want
// here you know what's the invoked function
// it's void foo(int)
// I'm returning its type to static_assert it
return &foo;
}
};
int main() {
float f = .42;
static_assert(find::which(0) == &static_cast<void(&)(int)>(foo), "!");
static_assert(find::which("hello") == &static_cast<void(&)(const char *)>(foo), "!");
static_assert(find::which(f) == &static_cast<void(&)(float&)>(foo), "!");
static_assert(find::which(.42) == &static_cast<void(&)(double&&)>(foo), "!");
}
在我希望专家诅咒我的短暂时间之后,我会删除这个答案。 : - )