【问题标题】:How should I do this explicit specialization?我应该如何做这个明确的专业化?
【发布时间】:2011-05-15 13:27:11
【问题描述】:

以下设计是否可行?:

template <typename T>
class Test{
 public:
  template <typename Z>
  void doSomething();
  //rest of things
 private:
  T obj;
  //some things
};

现在,如果可能的话,我会为 doSomething 做一些明确的专业化,这样最后我就会有一些版本,如下所示:

void doSomething<int>(){
 //do something
}
void doSomething<double>(){
 //do something
}
...etc

这似乎是不可能的,我找不到任何语法来完成这项工作,然后我想也许设计应该如下所示,以便所有模板参数都应该传递给模板类本身:

template <typename T,typename Z>
class Test{
 public:
  void doSomething();
  //rest of things
 private:
  T obj;
  //some things
};

然后我尝试了部分特化,它甚至没有编译:

template <typename T>
void Test<T,int>::doSomething(){
 //do something
}
template <typename T>
void Test<T,double>::doSomething(){
 //do something
}
...etc

我收到以下显式专业化错误:
错误#1:类模板名称后面的模板参数列表必须按照模板参数列表中使用的顺序列出参数。
错误#2:'Container1':模板参数太少。

【问题讨论】:

  • 你不能在标签上重载 doSomething 并使用省略号或通用模板来捕获所有内容吗?
  • @Tomek_没有明白你的意思,重点是模板。

标签: c++ templates explicit-specialization


【解决方案1】:

为了显式特化doSomething,您还必须显式特化Test

从 14.7.3/18 开始:

在明确的专业化中 类成员的声明 模板或成员模板 出现在命名空间范围内,成员 模板及其一些附件 类模板可能会保留 非专业化,除了 声明不得明确 专门化一个类成员模板,如果 它的封闭类模板不是 也明确专门化了

【讨论】:

  • 作为旁注,子类模板可以显式特化,而无需显式特化其所有封闭类模板。
【解决方案2】:

您不能显式特化成员模板,除非其封闭类模板也显式特化。

所以只有这样的东西才会起作用:

template<> template<>
void Test<int>::doSomething<int>()
{
}

【讨论】:

  • Smiljanic_"您不能显式特化成员模板,除非它的封闭类模板也显式特化。"不,那不对,请检查我的答案。
  • @Pooria:是的,这是真的,请参阅icecrime 的答案作为参考。
【解决方案3】:

你总是可以使函数内联

template <class T>
class Test
{
public:
 template <class Z>
 void doSomething() { cout << "default" << endl; }

 template<>
 void doSomething<int>() { cout << "int" << endl;}
 template<>
 void doSomething<double>() { cout << "double" << endl; }
private:
 T obj;
};

【讨论】:

  • 顺便说一下,我猜这是在 Visual C++ 2008 上编译的,因为我猜有一些错误! ;) .
  • 它也在 Visual C++ 2010 中为我编译,这就是我写它的原因。如果你在 Visual C++ 2010 中运行它也可以,所以我不值得 -1 :)
  • 至少对于 VC++ 2008 来说有趣的是,使用内联定义进行专门化时编译没有问题,但对于非内联定义的专门化,一旦有多个版本,它就不会成功编译。
【解决方案4】:

我觉得这个很挑剔。我想你做不到,阅读this

【讨论】:

    【解决方案5】:

    不确定这是否是 g++ 中的错误,但它可以编译并产生我期望的结果。

    #include<typeinfo>
    #include<iostream>
    
    template<typename T>
    class Test
    {
    public:
        template<typename Z>
        void doSomething();
    
    private:
        T obj;
    };
    
    template<typename T>
    template<typename Z>
    void Test<T>::doSomething()
    {
        Z val;
        std::cout << __func__ << ": type " << typeid(val).name() << std::endl;
    }
    
    int main(int argc, char *argv[])
    {
        Test<double> a;
        a.doSomething<int>();
        a.doSomething<double>();
    }
    

    【讨论】:

    • 这不是明确的专业化,所以根本没有错误。
    • 是的,它只是定义了模板化的成员函数。尝试了 Nikola Smiljanić,它适用于 g++。
    【解决方案6】:

    icecrime 发布了一个临时答案,它可能由于 Visual C++ 2008 的一些错误而被编译:

    template <typename T>
    class Test{
     public:
      template <typename Z>
      void doSomething();
      //rest of things
     private:
      T obj;
      //some things
    };
    template <>
    template <typename T>
    void Test<T>::doSomething<int>(){
     //do something
    }
    

    不过,请检查他当前的答案。 至少对于 VC++ 2008 来说有趣的是,使用内联定义进行专门化时编译没有问题,但对于具有非内联定义的专门化,一旦有多个版本,它就不会成功编译。

    【讨论】:

    • 在我的 g++ 版本上它不能编译。
    • 当它在 Visual C++ 2008 上完美编译时,为什么要投反对票?
    • 这个绝对不行。事实上,它不在 MSVC10 中。
    • 它不是有效的 C++,如果它为你编译它是一个编译器扩展或一个错误(取决于你如何看待事物)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 2010-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-12
    相关资源
    最近更新 更多