我想对一个结构进行专门化,其中一个使用函数指针而另一个不使用。但是,当我这样做时:
template <typename T, T*>
struct test;
template <typename T>
struct test<T, nullptr>
{
};
template <typename R, typename...ARGs, R(*fn)(ARGs...)>
struct test<R(ARGs...), fn>
{
};
我收到此错误:
error: type 'T*' of template argument 'nullptr' depends on a template parameter
struct test<T, nullptr>
这究竟是什么意思,我该如何运作?
答案 0 :(得分:4)
linked question描述了主要问题和一些解决方案,但由于它非常复杂,我已将它们应用于您的特定问题。
版本1
我们实际上可以使用std::integral_constant
来保存指针,因此我们可以利用这个事实来解决对非类型参数的限制:
template <typename T, typename U>
struct test;
template <typename T>
struct test<T, std::integral_constant<T*,nullptr>>
{
void operator()() { std::cout << "nullptr" << std::endl; }
};
template <typename R, typename...ARGs, R(*fn)(ARGs...)>
struct test<R(ARGs...), std::integral_constant<R(*)(ARGs...),fn>>
{
void operator()() { std::cout << "fnptr" << std::endl; }
};
不幸的是,这种用法看起来很丑陋,但它确实有效:
test<int,std::integral_constant<int*,nullptr>> a;
a();
test<decltype(foo), std::integral_constant<decltype(&foo), foo>> b;
b();
版本2
此版本使用std::enable_if
进行检查而非部分专业化:
template <typename T, T*, typename = void>
struct test;
template <typename T, T* P>
struct test<T, P, typename std::enable_if<(P==nullptr)>::type>
{
void operator()() { std::cout << "nullptr" << std::endl; }
};
template <typename T, T* P>
struct test<T, P, typename std::enable_if<std::is_function<T>::value>::type>
{
void operator()() { std::cout << "fnptr" << std::endl; }
};
这可能是你最初的意图:
test2<int, nullptr> c;
c();
test2<decltype(foo), foo> d;
d();
使用此版本,您无法即时访问用作模板参数的函数指针的参数类型,但如果需要,您可以轻松编写其他特征以获取它们。
这里有一个Live Demo,显示两个版本都在运行。