部分专用化非类型参数

partial specialization non type argument

本文关键字:类型参数 专用      更新时间:2023-10-16

我在这里需要一些帮助。我是元编程的新手,所以我什至不知道在哪里寻找解决方案(到目前为止我认为这甚至是不可能的)。

template<typename T, void(*FuncPtr_A)(int), int(*FuncPtr_B)() = nullptr>
class DummyClass
{ };
template<typename T, int(*FuncPtr_B)()>
class DummyClass<T, nullptr, FuncPtr_B>
{ };
void FUNC_A(int) { }
int FUNC_B() { return 0;  }
int main()
{
    DummyClass <int, FUNC_A, FUNC_B> test1;  // works
    DummyClass <int, FUNC_A> test2;          // works
    DummyClass <int, FUNC_B> test3;          // error: is there any way to make this work?
    return 0;
}

我能做的最好的事情就是:

namespace detail {
    template<typename T, void(*FuncPtr_A)(int), int(*FuncPtr_B)()>
    class DummyClass
    { };
}
template<class T, void(*FuncPtr_A)(int)>
auto DummyClass()
{
    return detail::DummyClass<T, FuncPtr_A, nullptr>();
}
template<class T, int(*FuncPtr_B)(void)>
auto DummyClass()
{
    return detail::DummyClass<T, nullptr, FuncPtr_B>();
}
template<class T, void(*FuncPtr_A)(int), int(*FuncPtr_B)(void)>
auto DummyClass()
{
    return detail::DummyClass<T, FuncPtr_A, FuncPtr_B>();
}


void FUNC_A(int) { }
int FUNC_B() { return 0;  }
int main()
{
    auto test1 = DummyClass <int, FUNC_A, FUNC_B>();  // works
    auto test2 = DummyClass <int, FUNC_A> ();          // works
    auto test3 = DummyClass <int, FUNC_B> ();          // works
    return 0;
}

编辑:

如果您需要命名类型(例如,用作类中的数据成员):

int main()
{
    decltype(DummyClass <int, FUNC_A, FUNC_B>()) test1 {};   // works
    decltype(DummyClass <int, FUNC_A> ()) test2 {};          // works
    decltype(DummyClass <int, FUNC_B> ()) test3 {};          // works
    return 0;
}

这不能在 C++11(也不是 C++14)中使用原始问题中的语法来完成,因为

  1. 您只能在模板参数列表的末尾默认模板参数,并且
  2. 不能让非类型模板参数
  3. 接受不同类型的参数值,除非根据 C++11 §14.3.2.5 中的转换规则规则,这些参数可转换为非类型模板参数的类型。

请注意,即使您传递了以这种方式可转换的参数,这也不能帮助您根据参数的原始类型专门化模板。

另请注意,1. 同样适用于函数默认参数,但是对于函数,您可以通过根据参数类型提供重载来解决此问题,这是 skypjack 对问题的评论和 RichardHodges 答案所依赖的工厂模式解决方法所依赖的技巧。