【问题标题】:Specialize a non-type template function with several values and the same specialization特化具有多个值和相同特化的非类型模板函数
【发布时间】:2020-10-10 17:25:29
【问题描述】:

我的意思是有一个依赖于size_t 模板参数的模板函数。 我有一个“后备”定义,放在我的sfinae.h

template <size_t dim>
int sumVec(void) {
    return -1;
}

我已经对dim 的特定值进行了一些专门化,例如在我的sfinae.cc

template <>
int sumVec<2>(void) {
    return 2;
};

及其原型在sfinae.h

现在我想定义一个适用于dim 的多个值的特化,所以我的意思是避免多次复制它。 我可以将dim 变成enum class,就像在One template specialization for several enum values 中所做的那样

我的问题是 我能否在不(大量)更改我拥有的代码(但我可以添加代码)的情况下实现我的目标?

我尝试在标头或源代码中添加代码,编译器(gcc 10.2.0)抛出错误non-class, non-variable partial specialization 'sumVec&lt;std::enable_if&lt;((dim == 3) || (dim == 4)), void&gt; &gt;' is not allowed 所以我不确定我没有使用正确的方法或语法,或者我的要求是编译器不允许的。

template<size_t dim>
int sumVec<std::enable_if<dim == 3 || dim == 4>>(void)
{
    return dim;
};

【问题讨论】:

  • 您可能只有一个类并在其实现中使用if constexpr,这取决于您要实际实现的目标
  • 不改变 sfinae.h.
  • @AlanBirtles - 到目前为止我没有任何课程。我欢迎您发布一个简短的示例来说明您的想法。至于我要做什么,解释起来会很长,我不确定它会改变问题......我想这不应该被视为XY Problem,我目前对发布的MCVE感兴趣......如果不够清楚,请告诉我。
  • @bipll - 查看更新的 OP...我的意思是不要大幅更改它。

标签: c++ templates template-specialization


【解决方案1】:

函数模板不能部分特化。您可以通过重载的方式应用 SFINAE,这需要更改主模板以避免模棱两可的调用。

// primary template overloading #1
template<size_t dim>
std::enable_if_t<dim != 3 && dim != 4, int> sumVec(void)
{
    return -1;
}

// primary template overloading #2
template<size_t dim>
std::enable_if_t<dim == 3 || dim == 4, int> sumVec(void)
{
    return dim;
}

// full specialization
template <>
int sumVec<2>(void) {
    return 2;
}

【讨论】:

  • 这行得通,如果将所有内容都放在标题中。在源中放置定义的正确方法是什么,只在标题中留下原型?我尝试声明 inline 几种组合,但我没有得到决定正确组合的理由。
  • @sancho.sReinstateMonicaCellio 这并不容易完成。 Why can templates only be implemented in the header file?
  • 我意识到了这一点,实际上我过去曾支持过它。但是我在其他地方的源代码中使用了显式实例化,例如此外,这里我的sumVec&lt;2&gt; 是在源代码中定义的。但我无法在源代码中定义两个std::enable_if_t...。我想如果选择合适的inlines(我没有得到)它应该可以工作。
  • @sancho.sReinstateMonicaCellio 主模板必须在使用它们的每个翻译单元中可见,我认为必须将它们放置在听者中并在必要时包含在内。顺便说一句:如果您将专业化放在 cc 文件中,该文件不包括在内,即在翻译单元中不可见,则将调用主模板。
  • "函数模板不能部分特化。"不完全正确。您可以在主定义中使用if constexpr 获得某种 程度的部分专业化。
【解决方案2】:

您可以避免使用 if constexpr 进行模板特化,而只需拥有您的类的单个实例:

template <size_t dim>
int sumVec(void) {
    if constexpr (dim == 2) {
       return 2;
    }
    if constexpr (dim == 3 || dim == 4) {
       return dim;
    }
    return -1;
}

【讨论】:

    猜你喜欢
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-16
    • 1970-01-01
    • 2017-07-18
    • 1970-01-01
    相关资源
    最近更新 更多