我想提取函数的返回类型。问题是,还有其他函数具有相同的名称但签名不同,我无法让C ++选择合适的函数。我知道std :: result_of,但是从几次尝试我得出结论它也遇到了同样的问题。我也听说过涉及decltype的解决方案,但我不知道具体细节。
目前我正在使用模板元编程从函数指针类型中提取返回类型,对于有限数量的参数(任何非限制解决方案?)都可以正常工作,因为函数指针类型的提取适用于明确的功能
#include <iostream>
using namespace std;
// ----
#define resultof(x) typename ResultOf<typeof(x)>::Type // might need a & before x
template <class T>
class ResultOf
{
public:
typedef void Type; // might need to be T instead of void; see below
};
template <class R>
class ResultOf<R (*) ()>
{
public:
typedef R Type;
};
template <class R, class P>
class ResultOf<R (*) (P)>
{
public:
typedef R Type;
};
// ----
class NoDefaultConstructor
{
public:
NoDefaultConstructor (int) {}
};
int f ();
int f ()
{
cout << "f" << endl;
return 1;
}
double f (int x);
double f (int x)
{
cout << "f(int)" << endl;
return x + 2.0;
}
bool f (NoDefaultConstructor);
bool f (NoDefaultConstructor)
{
cout << "f(const NoDefaultConstructor)" << endl;
return false;
}
int g ();
int g ()
{
cout << "g" << endl;
return 4;
}
int main (int argc, char* argv[])
{
if(argc||argv){}
// this works since there is no ambiguity. does not work without &
// resultof(&g) x0 = 1;
// cout << x0 << endl;
// does not work since type of f is unknown due to ambiguity. same thing without &
// resultof(&f) x1 = 1;
// cout << x1 << endl;
// does not work since typeof(f()) is int, not a member function pointer; we COULD use T instead of void in the unspecialized class template to make it work. same thing with &
// resultof(f()) x2 = 1;
// cout << x2 << endl;
// does not work per above, and compiler thinks differently from a human about f(int); no idea how to make it correct
// resultof(f(int)) x3 = 1;
// cout << x3 << endl;
// does not work per case 2
// resultof(f(int())) x4 = 1;
// cout << x4 << endl;
// does not work per case 2, and due to the lack of a default constructor
// resultof(f(NoDefaultConstructor())) x5 = 1;
// cout << x5 << endl;
// this works but it does not solve the problem, we need to extract return type from a particular function, not a function type
// resultof(int(*)(int)) x6 = 1;
// cout << x6 << endl;
}
任何想法我缺少什么语法功能以及如何解决它,最好使用一种简单方法的解决方案,例如: resultof(f(int))
?
答案 0 :(得分:8)
我认为可以使用decltype
和declval
:
例如:decltype(f(std::declval<T>()))
。
答案 1 :(得分:1)
在没有参数的情况下检查重载的函数名称非常困难。您可以检查arity不同的重载的返回类型 - 前提是没有arity有多个重载。即便如此,将一个硬错误(如果/当一个给定的arity确实有一个以上的重载)转换为SFINAE是一件痛苦的事情,因为它需要为该特定函数(!)编写特征,因为重载的函数名称不能传递给任何形式的争论。不妨要求用户代码使用明确的专业化......
template<typename R>
R
inspect_nullary(R (*)());
template<typename R, typename A0>
R
inspect_unary(R (*)(A0));
int f();
void f(int);
int g();
double g();
typedef decltype(inspect_nullary(f)) nullary_return_type;
typedef decltype(inspect_unary(f)) unary_return_type;
static_assert( std::is_same<nullary_return_type, int>::value, "" );
static_assert( std::is_same<unary_return_type, void>::value, "" );
// hard error: ambiguously overloaded name
// typedef decltype(inspect_nullary(g)) oops;
鉴于您使用的是C ++ 0x,我觉得有必要指出(IMO)从不需要检查超出typename std::result_of<Functor(Args...)>::type
的返回类型,这不适用于函数名称;但也许你对此的兴趣纯粹是学术上的。
答案 2 :(得分:0)
好的,经过几次尝试后,我设法解决了Mankarse建议的std::declval
方法。我使用了可变参数类模板来固定参数,并使用模板推导函数来从函数指针获取返回值。它目前的语法是typeof(ResultOf<parameters>::get(function))
,遗憾的是它仍然远离期望的resultof<parameters>(function)
形式。如果我找到进一步简化它的方法,将编辑此答案。
#include <iostream>
#include <typeinfo>
using namespace std;
template <class... Args>
class ResultOf
{
public:
template <class R>
static R get (R (*) (Args...));
template <class R, class C>
static R get (R (C::*) (Args...));
};
class NoDefaultConstructor
{
public:
NoDefaultConstructor (int) {}
};
int f ();
double f (int x);
bool f (NoDefaultConstructor);
int f (int x, int y);
int main (int argc, char* argv[])
{
if(argc||argv){}
cout << typeid(typeof(ResultOf<>::get(f))).name() << endl;
cout << typeid(typeof(ResultOf<int>::get(f))).name() << endl;
cout << typeid(typeof(ResultOf<NoDefaultConstructor>::get(f))).name() << endl;
cout << typeid(typeof(ResultOf<int, int>::get(f))).name() << endl;
typeof(ResultOf<int>::get(f)) d = 1.1;
cout << d << endl;
}
编辑:
管理用可变参数宏解决它,语法现在是resultof(f, param1, param2, etc)
。没有它们,我无法将参数类型之间的逗号传递给模板。尝试使用语法resultof(f, (param1, param2, etc))
无济于事。
#include <iostream>
using namespace std;
template <class... Args>
class Param
{
public:
template <class R>
static R Func (R (*) (Args...));
template <class R, class C>
static R Func (R (C::*) (Args...));
};
#define resultof(f, ...) typeof(Param<__VA_ARGS__>::Func(f))
int f ();
double f (int x);
int f (int x, int y);
int main (int argc, char* argv[])
{
resultof(f, int) d = 1.1;
cout << d << endl;
}