Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 具有多个模板参数的模板专门化_C++_Templates_Template Specialization - Fatal编程技术网

C++ 具有多个模板参数的模板专门化

C++ 具有多个模板参数的模板专门化,c++,templates,template-specialization,C++,Templates,Template Specialization,假设我有这个: template<typename T, int X> class foo { public: void set(const T &t); }; template<typename T, int X> void foo::set<T, X>(const T &t) { int s = X; // ...etc } 模板 福班 { 公众: 无效集(常数T&T); }; 模板 void foo::set(常量T&T

假设我有这个:

template<typename T, int X>
class foo 
{
public:
  void set(const T &t);
};

template<typename T, int X>
void foo::set<T, X>(const T &t)
{
  int s = X;
  // ...etc
}
模板
福班
{
公众:
无效集(常数T&T);
};
模板
void foo::set(常量T&T)
{
int s=X;
//…等等
}
我是否可以专门化函数类型“T”,但保留“X”作为模板参数

class bar;

template<int X>
void foo::set<bar, X>(const bar &t)
{
  int s = X;
  // ...etc
}
类条;
模板
void foo::set(常数条&t)
{
int s=X;
//…等等
}

这可能吗?

不可能。这是不允许的。
成员函数必须是完全专用的。比如说应该是,

template<>
void foo<bar, 5>::set(const bar &t)
{          //^^^^
  int s = 5;
  // ...etc
}
模板
void foo::set(常数条&t)
{          //^^^^
int s=5;
//…等等
}

一旦你掌握了窍门,这就非常容易了

template<typename T, int X>
class foo 
{
private:
  template<typename, int> class params { };

public:
  void set(const T &t) {
    set(t, params<T, X>());
  }

private:
  template<typename T1, int X1>
  void set(const T1 &t, params<T1, X1>) {
     // ...
  }

  template<int X1>
  void set(const bar &t, params<bar, X1>) {
    // ...
  }
};
模板
福班
{
私人:
模板类参数{};
公众:
无效集(常数T&T){
set(t,params());
}
私人:
模板
无效集(常数T1&t,参数){
// ...
}
模板
无效集(常数棒和t,参数){
// ...
}
};

这是必要的,因为如果显式专门化单个成员,则必须提供所有模板参数。你不能漏掉一些

您可以部分地专门化整个类。在这种情况下,您可以为类的每一个专业化提供不同的实现到<代码> SET/COD>函数。

< P>您可以考虑改写代码,使成员函数成为单独的模板:

template <int X> class foo
{
  template <typename T> void set(const T &);
  // ...
};
模板类foo
{
模板无效集(常数T&);
// ...
};

然后,您可以为模板
foo::set

void foo::set(const T&T)
->
void foo::set(const T&T)
提供明确的专门化,这是正确的,但我个人会避免这样的把戏。它使代码无法读取。IMO根据情况对类进行部分专门化或类似的操作(例如,创建基类模板并对其进行部分专门化,并在非专门化的派生类中实现(许多?)非专门化函数)是更好的决定。@Serge部分专门化整个类。因此,如果他只想要单个函数的特殊行为,这是不合适的。创建基础模板会带来更多的噪音和不便(您将无法访问“foo”的成员,…)。如果你有一个更干净的解决方案,我欢迎你发布它。“部分专业化专门化整个类”-真的。“创建一个基础模板会带来更多的噪音和不便”-通常不会带来不便-这是一个小的额外工作,以使架构保持一致。如果需要专门化,那么通常情况下,这种情况下有一些特殊的逻辑,可能需要单独的(基本)类专门化。如果有很多公共成员对象,那么将它们(受保护)放在另一个类中作为两个父专门化的基础是没有问题的(这背后通常有一个逻辑)。我知道这听起来很复杂,但如果每件事都能始终如一地实现,那么它比重载技巧可读性强得多。@Serge我不明白你为什么认为这两个重载是不可读的。依我看,它们是最可读的解决方案。@MarkP,检查答案。