【问题标题】:Rules for partial specialization of templates with nontype parameter(s)带有非类型参数的模板的部分特化规则
【发布时间】:2021-11-03 13:11:10
【问题描述】:

考虑以下模板

template <typename T, int v> void func(const T&x);

我想将它专门用于某个课程A。这是我的尝试(参考this):

template <int v> void func<A, v>(const A&x);

但是,这是非法的。我的问题是为什么这是非法的(它违反了哪条规则),如果这违反语法,我们是否有其他方法可以将其专门用于 A

【问题讨论】:

  • 你可以做template &lt;int v&gt; void func(const A&amp;x);
  • @appleapple 但这不是在创建另一个模板吗?
  • 有什么区别?你能展示一下你想如何使用它吗?
  • 您不能部分专门化函数。参见templates“部分特化只允许用于类模板[和变量模板(C++14 起)]。”
  • BTW 更好地反转模板参数顺序,因为T 是可推断的:template &lt;int v, typename T&gt; void func(const T&amp;x); 允许调用,例如func&lt;42&gt;(my_obj);

标签: c++ templates generics


【解决方案1】:

您不能部分特化函数模板,但您可以重载它,如下所示。

#include <iostream>
class A 
{
    
};

template <typename T, int v> void func(const T&x) //primary template
{
    std::cout<<"primary template"<<std::endl;
}
//this is an overload and not a specialization. Also partial specialization cannot be done for function templates
template <int v> void func(const A&x)
{
    std::cout<<"overload not specialization"<<std::endl;
}
int main()
{
    func<int, 5>(84); //uses primary template 
    
    func<5>(A()); //uses the overloaded version
    return 0;
}

【讨论】:

    【解决方案2】:

    函数模板不能部分特化,因此报错:

    <source>:8:23: error: non-class, non-variable partial specialization 'func<A, v>' is not allowed
        8 | template <int v> void func<A, v>(const A&x);
          |                       ^~~~~~~~~~
    

    例如,您可以使用 operator() 部分特化一个类型:

    template <typename T, int v>
    struct func{
        void operator()(const T&x);
    };
    
    struct A {};
    
    template <int v> 
    struct  func<A, v>{
        void operator()(const A&x);
    };
    

    【讨论】:

    • 感谢您的回答!我也想到了使用函数对象的可能性,我会尝试的!
    【解决方案3】:

    您可以使用约束(或 SFINAE)来做到这一点。

    #include <iostream>
    class A {};
    class B {};
    
    template <typename T, int v> void func(const T&)
    {
        std::cout<<"generic";
    }
    
    template <typename T, int v> void func(const T&)
    requires std::is_same_v<T,A>
    {
        std::cout<<"A";
    }
    
    int main(){
        func<A,1>(A{}); // output A
    }
    

    https://godbolt.org/z/YcxeoofYE

    【讨论】:

      【解决方案4】:
      这里没有推导出v,这可能会导致不良影响,请留在这里,因为它可能对有人提出这个问题有用。

      你可以这样做

      template <typename T, int v> void func(const T&x);
      template <int v> void func(const A&x);
      

      至于为什么,我认为主要是因为它没有提供额外的价值

      template <typename T> void func(const T&x);
      template <typename T> void func(const T*x);
      void func(const A&);
      

      已经是一个有效的函数“专业化”在标准措辞意义上并不是真正的专业化

      【讨论】:

      • 你错了。您称为专业化的最后两个版本是重载。
      • @AanchalSharma 我没有称它们为专业化,这就是我引用它们并使用斜体的原因
      • is already a valid function "specialization". 在我看来,您称他们为专业化。也许你可以把你的意思写得更清楚,以免混淆。
      • @AanchalSharma 添加了。
      猜你喜欢
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-16
      • 1970-01-01
      相关资源
      最近更新 更多