使用参数包专门化模板 类
Specializing Template Classes with Parameter Packs
我正在使用一组 classes 的继承。其中一个子 classes 接受 std::function(ReturnTy<ParamTypes...>)
以及 ParamTypes
参数。 class 签名和构造函数如下所示:
template<class ReturnTy, class... ParamTypes>
class Child : public Interface
{
public:
Child(ReturnTy default_value, ParamTypes... args)
: func_set_(false)
, m_Args(std::make_tuple(std::forward<ParamTypes>(args)...))
, m_ReturnValue(default_value)
{}
private:
bool func_set_;
std::function<ReturnTy(ParamTypes...)> m_Funciton;
std::tuple<ParamTypes...> m_Args;
ReturnTy m_ReturnValue;
};
我的问题是当我想专门处理没有参数的情况时。此外,我还想专门针对 ReturnTy=void
并且有参数的情况。我找到了一个接近我正在寻找的答案 here,但它并不完全涵盖我正在尝试做的事情,因为该问题使用编译时整数作为模板参数,我在这里使用类型。它还涉及函数而不是 classes。我觉得我很接近,但我只需要一些帮助来使我的代码正常工作。
作为参考,这是我对其他专业的了解(缩写):
template<class ReturnTy>
class Child<ReturnTy> : public Interface
{
public:
Child(ReturnTy default_value)
: // The same as first class without m_Args
{}
private:
// Same as first class without m_Args
};
template<class... ParamTypes>
class Child<void, ParamTypes...> : public Interface
{
public:
Child(ParamTypes... args)
: // Same as first class without m_ReturnValue
private:
// Same as first class without m_ReturnValue
};
编辑
具体来说,问题来自类似以下代码行:
Child<void> obj1(5);
问题是你们的专业水平相同(没有一个比另一个更专业)并且 Child<void>
两者都匹配。
如果您希望 Child<void>
匹配 Child<ReturnTy>
情况(否则解决方案简单而优雅:在第二个专业化中,将 ParamTypes...
列表拆分为 Par0
强制类型和其余 ParamTypes...
) 我没有看到一个简单而优雅的解决方案。
目前,我能想到的最好的办法是添加一个间接级别(添加一个 Child_base
class),同时添加一个模板参数来明确所需的解决方案。
也许可以用更简单的方式来制作(抱歉,现在,我可以尝试使用编译器)但我想象如下
template <typename RT, bool, typename ... PTs>
class Child_base : public Interface
{
// general case (no empy PTs... list and no void return type)
};
template <typename ... PTs>
class Child_base<void, true, PTs...> : public Interface
{
// case return type is void (also empy PTs... list)
};
template <typename RT>
class Child_base<RT, false> : public Interface
{
// case return type only, but not void, and empy PTs
};
template <typename RT, typename ... PTs>
class Child
: public Child_base<RT, std::is_same_v<void, RT>, PTs...>
{
};
这样,Child<void>
继承自 Child_base<void, true>
,匹配 Child_base
的第一个特化,但不匹配第二个。
我提出关于 Child
的另一种方式:与其将其定义为从 Child_base
派生的 class,不如将其定义为 using
的别名 Child_base
template <typename RT, typename ... PTs>
using Child = Child_base<RT, std::is_same_v<void, RT>, PTs...>;
也许用更合适的名称重命名 Child_base
。
问题是 Child<void>
匹配 2 个(部分)专业(其中 none 比另一个更专业):
template<class ReturnTy> class Child<ReturnTy>
与 [ReturnTy = void]
template<class... ParamTypes> class Child<void, ParamTypes...>
空包。
你需要额外的专业化:
template<>
class Child<void> : public Interface
{
public:
Child() = default;
// ....
private:
std::function<void()> m_Function;
};
我正在使用一组 classes 的继承。其中一个子 classes 接受 std::function(ReturnTy<ParamTypes...>)
以及 ParamTypes
参数。 class 签名和构造函数如下所示:
template<class ReturnTy, class... ParamTypes>
class Child : public Interface
{
public:
Child(ReturnTy default_value, ParamTypes... args)
: func_set_(false)
, m_Args(std::make_tuple(std::forward<ParamTypes>(args)...))
, m_ReturnValue(default_value)
{}
private:
bool func_set_;
std::function<ReturnTy(ParamTypes...)> m_Funciton;
std::tuple<ParamTypes...> m_Args;
ReturnTy m_ReturnValue;
};
我的问题是当我想专门处理没有参数的情况时。此外,我还想专门针对 ReturnTy=void
并且有参数的情况。我找到了一个接近我正在寻找的答案 here,但它并不完全涵盖我正在尝试做的事情,因为该问题使用编译时整数作为模板参数,我在这里使用类型。它还涉及函数而不是 classes。我觉得我很接近,但我只需要一些帮助来使我的代码正常工作。
作为参考,这是我对其他专业的了解(缩写):
template<class ReturnTy>
class Child<ReturnTy> : public Interface
{
public:
Child(ReturnTy default_value)
: // The same as first class without m_Args
{}
private:
// Same as first class without m_Args
};
template<class... ParamTypes>
class Child<void, ParamTypes...> : public Interface
{
public:
Child(ParamTypes... args)
: // Same as first class without m_ReturnValue
private:
// Same as first class without m_ReturnValue
};
编辑
具体来说,问题来自类似以下代码行:
Child<void> obj1(5);
问题是你们的专业水平相同(没有一个比另一个更专业)并且 Child<void>
两者都匹配。
如果您希望 Child<void>
匹配 Child<ReturnTy>
情况(否则解决方案简单而优雅:在第二个专业化中,将 ParamTypes...
列表拆分为 Par0
强制类型和其余 ParamTypes...
) 我没有看到一个简单而优雅的解决方案。
目前,我能想到的最好的办法是添加一个间接级别(添加一个 Child_base
class),同时添加一个模板参数来明确所需的解决方案。
也许可以用更简单的方式来制作(抱歉,现在,我可以尝试使用编译器)但我想象如下
template <typename RT, bool, typename ... PTs>
class Child_base : public Interface
{
// general case (no empy PTs... list and no void return type)
};
template <typename ... PTs>
class Child_base<void, true, PTs...> : public Interface
{
// case return type is void (also empy PTs... list)
};
template <typename RT>
class Child_base<RT, false> : public Interface
{
// case return type only, but not void, and empy PTs
};
template <typename RT, typename ... PTs>
class Child
: public Child_base<RT, std::is_same_v<void, RT>, PTs...>
{
};
这样,Child<void>
继承自 Child_base<void, true>
,匹配 Child_base
的第一个特化,但不匹配第二个。
我提出关于 Child
的另一种方式:与其将其定义为从 Child_base
派生的 class,不如将其定义为 using
的别名 Child_base
template <typename RT, typename ... PTs>
using Child = Child_base<RT, std::is_same_v<void, RT>, PTs...>;
也许用更合适的名称重命名 Child_base
。
问题是 Child<void>
匹配 2 个(部分)专业(其中 none 比另一个更专业):
template<class ReturnTy> class Child<ReturnTy>
与[ReturnTy = void]
template<class... ParamTypes> class Child<void, ParamTypes...>
空包。
你需要额外的专业化:
template<>
class Child<void> : public Interface
{
public:
Child() = default;
// ....
private:
std::function<void()> m_Function;
};