【问题标题】:Creating multiple class implemetations based on template parameter基于模板参数创建多个类实现
【发布时间】:2019-10-17 09:16:56
【问题描述】:

我有一个模板类 G:

template<int I>
class G {}

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

如果它是一个单一的值,我总是能够做到:

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

如果我有单一条件,即如果为真则使用 implementation_1,如果为假则使用 implementation_2,我可以使用给定 here 的建议


但是,我的情况比较一般。

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

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

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

这样便于阅读和根据需要进行扩展
如果在程序中调用特定I 时,由于没有或多个条件适用于特定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>’|

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

【问题讨论】:

  • 我发誓,如果我得到一个链接到我已经解释为“没有解决我的问题”的问题的“重复”标签......
  • 这个问题还不清楚。你想要 I==0I==1 的不同定义吗?
  • 你定义了两次错误告诉你的相同模板,但不清楚你想要实现什么
  • @foreknownas_463035818 正如我所说的,我在每个实现中都有constexprI 条件
  • “在每个实现中”是什么意思?你有Condition_1Condition_2 并且你想根据其中一个是否为true 来选择实现?

标签: c++ templates enable-if


【解决方案1】:

您的错误是您没有调整主模板以正确使用成语。如果您想添加那些解析为voidenable_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,以便您的专业化条件匹配。当两个条件都成立时,这当然会导致错误,但是您确实断言这对您来说没问题,所以就这样吧。

【讨论】:

  • 哦,当然……我只输入1个参数,所以template的括号内必须只有int I
  • 不理解反对票。我将删除主要G 的定义(或在其中放置static_assert)以覆盖(如产生错误)不满足条件的情况。但这个答案似乎很完美。
  • @MaximEgorushkin - 啊,我明白了,这是因为您不了解偏序以及模板签名中的内容。你为什么不直接说?我可以解释
  • @MaximEgorushkin - 我做到了,of course。您的尝试是否同时满足这两个条件?
  • 当然我触发了这两个条件,因为它们是独立的条件。如果不是,它们不应该是 2 个不同的条件,并且您的解决方案没有意义。问题需要针对不同条件的 2 种不同实现,而您的解决方案没有提供。更不用说这里不需要enable_if_t
【解决方案2】:

你不需要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>.

【讨论】:

  • 现在想象 5 个实现,每个都有自己的条件。 10?您的解决方案无法扩展。
  • 但是......如果我需要跟踪每个条件组合,它实际上会很有用。有没有办法组合一些组合? (即,使 false-false 和 true-false 指代相同的实现而无需复制粘贴)(我的意思是没有摆脱单个参数的子模板,因为这将不允许组合两对例如)
  • 好的,我重新考虑了你的方法。我仍然认为它不能扩展(严格地由于可读性)。但我认为如果仔细完成它确实允许组合
  • @NooneAtAll 为您添加了替代方案。
猜你喜欢
  • 2022-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多