2017-02-28 223 views
8

我只是偶然发现了一个小问题,这个问题在处理模板时给我带来了困扰。这里有一个例子:模板函数指针作为模板参数

template<class _returnType, _returnType (*_function)()> 
_returnType aliasGetter() { return _function(); } 
int getCoolNumber() { return 42; } 
int main() 
{ 
    std::cout << aliasGetter<int, &getCoolNumber>(); //42 
} 

此代码(http://cpp.sh/,如果你想尝试一下),但是因为我给一个函数指针作为模板参数我不应该需要_returnType,这是正确的,在函数签名,问题是,不管我多努力尝试,我都找不到一种方法来摆脱这个额外的模板参数。

我该如何让aliasGetter只接受一个模板参数(指向getter指向别名的指针)? 如果这是不可能的,为什么不呢?

+0

如何使用单个模板参数并依赖模板参数扣除? – WhiZTiM

+1

@WhiZTiM这需要在运行时将函数指针传递给调用。 –

+0

您需要它,因为您的第二个模板参数依赖于它。你可以用https://functionalcpp.wordpress.com/2013/08/05/function-traits/建立一些东西,但我怀疑你会保存一个模板参数。 – knivil

回答

14

在C++ 17,这将成为可能,这要归功于template auto

template <auto F> std::invoke_result_t<F> aliasGetter() { return F(); } 

之前C++ 17,这是不可能的。您需要指定非类型模板参数的类型 - 这是没有办法的。您无法为此创建工厂,因为您无法通过函数模板传递函数指针,并将其作为非类型模板参数传递。


在C++ 14的最短的解决方法是,叹息,使用宏:

template <class T, T F> std::result_of_t<T()> aliasGetter() { return F(); } 
#define TEMP_ALIAS(x) decltype(x), x 

std::cout << aliasGetter<TEMP_ALIAS(&getCoolNumber)>(); 

它可以让你的函数指针的类型,您无需手动输入两次。

+1

我知道使用C + 17可能会感谢您所描述的新语法,但是,我认为也许它可以在没有这种魔术的情况下完成(这就是为什么我标记了C++ 14)。虽然 – Nyashes

+0

C++ 17上的'std :: result_of'为[deprecated](http://en.cppreference.com/w/cpp/types/result_of),但它仍然是一个很好且清晰的答案,请使用'std :: invoke_result相反。 –