基于模板参数创建多个类实现

Creating multiple class implemetations based on template parameter

本文关键字:实现 创建 于模板 参数      更新时间:2023-10-16

>我有一个模板化类 G:

template<int I>
class G {}

碰巧我需要基于该int I的 2 个实现

如果它是一个值,我将始终能够做到:

template<>
class G<int Specific_I>
{
/*Implementation for that I*/
}

如果我有单一条件,表明如果为真,则使用implementation_1,如果为假,则使用implementation_2,我可以使用此处给出的建议


但是,我的情况更普遍。

假设我为每个实现定义了I条件:

template<int I>
constexpr bool Condition_1 = /*whatever*/;
template<int I>
constexpr bool Condition_2 = /*whatever_v2*/;

这允许根据需要轻松
读取和扩展 如果在程序中调用时由于没有或多个条件适用于特定I而出现错误,我对此很好

显而易见的选择是使用std::enable_if_t

template<int I,
enable_if_t<Condition_1<I>>
>
class G
{
/*Implementation based on Condition_1*/
}
template<int I,
enable_if_t<Condition_2<I>>
>
class G
{
/*Implementation based on Condition_2*/
}

但这会导致错误

template parameter ‘typename std::enable_if<Condition_1<I>, void>::type <anonymous>’|
redeclared here as ‘typename std::enable_if<Condition_2<I>, void>::type <anonymous>’|

我在哪里犯了错误,我该如何解决?

您的错误在于您没有调整主模板以正确使用习语。如果要添加解析为void的那些enable_if,主模板声明需要该位置的类型参数:

template<int I, typename = void>
class G; // Or static_assert in the definition. Whichever flavor you prefer.
template<int I>
class G< I, enable_if_t<Condition_1<I>> >
{
/*Implementation based on Condition_1*/
};
template<int I>
class G< I, enable_if_t<Condition_2<I>> >
{
/*Implementation based on Condition_2*/
};

注意:必须为具有匹配条件的专业void默认参数。当两个条件都成立时,这当然会导致错误,但你确实断言这对你很好,所以你去吧。

这个问题不需要std::enable_if。由于您的条件是独立的,因此它们应该初始化不同的模板参数:

template<int I, bool C1 = Condition_1<I>, bool C2 = Condition_2<I>>
struct G;
// Specializations for different conditions.
template<int I> struct G<I, false, false> { /*...*/ };
template<int I> struct G<I, false,  true> { /*...*/ };
template<int I> struct G<I,  true, false> { /*...*/ };
template<int I> struct G<I,  true,  true> { /*...*/ };

或者,您可以将条件组合成一个参数:

template<int I, unsigned C = (Condition_1<I> | Condition_2<I> * 2)>
struct G;
// Specializations for different conditions.
template<int I> struct G<I, 0> { /*...*/ };
template<int I> struct G<I, 1> { /*...*/ };
template<int I> struct G<I, 2> { /*...*/ };
template<int I> struct G<I, 3> : G<I, 2> { /*...*/ }; // Same as G<I, 2>.