我在C ++中寻找一种方法来提取函数的返回类型(不调用它)。我认为这需要一些模板魔术。
float Foo();
int Bar();
magic_template<Foo>::type var1; // Here 'var1' should be of type 'float'
magic_template<Bar>::type var2; // and 'var2' should be of type 'int'
我目前正在研究如何实施magic_template
,但到目前为止尚未找到解决方案。
有什么想法吗?
答案 0 :(得分:7)
看一下boost type traits库,特别是function_traits
模板提供了开箱即用的功能。如果你不能使用boost,只需下载代码并阅读源代码,以便了解它是如何完成的。
请注意,该功能基于类型,而不是具体功能,因此您可能需要在那里添加一些额外的代码。
在做了一些小测试之后,这可能不是你真正需要的,如果它是'一些额外的代码'将是非平凡的。问题是function_traits
模板适用于函数签名而不是实际的函数指针,因此问题已经从'从函数指针获取返回类型'变为'从函数指针获取签名'这可能是那里最难的部分。
答案 1 :(得分:5)
这很棘手,因为函数名称的表达式不是类型 - 你需要像gcc的typeof
这样的东西。 Boost的TypeOf是一种非常接近的便携式解决方案。
但是,如果可以对代码进行组织,以便在可以传递Foo
或Bar
的函数模板内完成工作,那么可以直截了当地回答:
template <class R>
void test(R (*)())
{
R var1;
}
int main()
{
test(&Foo);
}
答案 2 :(得分:5)
Foo和Bar是函数,而不是函数类型,所以你需要做一些额外的工作。
这是使用boost :: function_traits和BOOST_TYPEOF组合的解决方案。
#include <boost/typeof/typeof.hpp>
#include <boost/type_traits.hpp>
float Foo();
int Bar();
int main()
{
boost::function_traits<BOOST_TYPEOF(Foo)>::result_type f = 5.0f;
boost::function_traits<BOOST_TYPEOF(Bar)>::result_type i = 1;
return i;
}
编辑:
答案 3 :(得分:2)
在C ++ 0x中,使用decltype
。
有关问题的讨论并尝试构建早期C ++标准的解决方案,请参见此处:
Scott Myers "challenge"(PDF)和Andrei Alexandrescu trying to solve it
答案 4 :(得分:1)
模板魔术(不涉及Boost
):
template <typename ReturnType> class clFunc0
{
typedef ReturnType ( *FuncPtr )();
public:
typedef ReturnType Type;
};
template <typename ReturnType> inline clFunc0<ReturnType> ResultType( ReturnType ( *FuncPtr )() )
{
return clFunc0<ReturnType>();
}
#define FUNC_TYPE( func_name ) decltype( ResultType( &func_name ) )::Type
int test()
{
return 1;
}
int main()
{
FUNC_TYPE( test ) Value = 1;
return Value;
}
通过
编译gcc Test.cpp -std=gnu++0x
答案 5 :(得分:0)
正如dribeas所说,这是我最终得到的解决方案:
float Foo();
int Bar();
template<typename T> Monkey(T) {
boost::function_traits< boost::remove_pointer<T>::type >::result_type var1 = ...;
// Now do something
}
Monkey(Foo);
Monkey(Bar);
这不是我原来的问题所针对的形式,但它对我来说足够接近。
答案 6 :(得分:-1)
尝试这样的事情:
template<class T> struct magic_template
{};
template<class T> struct magic_template<T()>
{
typedef T type;
};