Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.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 - Fatal编程技术网

C++ 为什么这些模板模棱两可?

C++ 为什么这些模板模棱两可?,c++,templates,C++,Templates,这本书在第275页有一个例子,我很难理解 引用书中的摘录 template <typename T> class Promotion<T,T> { public: typdef T ResultT; }; template<typename T1, typename T2> class Promotion<Array<T1>, Array<T2> > { public: typedef Array&

这本书在第275页有一个例子,我很难理解

引用书中的摘录

template <typename T>
class Promotion<T,T> {
  public:
    typdef T ResultT;
};

template<typename T1, typename T2>
class Promotion<Array<T1>, Array<T2> > {
  public:
    typedef Array<typename Promotion<T1,T2>::ResultT> ResultT;
};

template<typename T>
class Promotion<Array<T>, Array<T> > {
  public:
    typedef Array<typename Promotion<T,T>::ResultT> ResultT;
};
模板
班级晋升{
公众:
典型结果;
};
模板
班级晋升{
公众:
typedef数组结果;
};
模板
班级晋升{
公众:
typedef数组结果;
};
不幸的是,部分专业化
升级
是无效的
既不比部分专业化更专业化,也不比部分专业化更专业化
促销
。为避免模板选择不明确,最后一部分 增加了专门化。它比以前的任何一种都更专业 两个部分专业


为什么前两个模板模棱两可,为什么最后一个模板解决了模棱两可的问题?当我尝试应用这些规则时,我要么不知道它是如何产生歧义的,要么如果我认为我有办法做到这一点,我不知道为什么最后一个模板可以解决这个问题。

歧义是指同一个类可以从不同的专门化实例化,编译器不能支持一个专门化而不是另一个专门化,因为两者都不是更专业的。添加一个更专门的版本会使编译器选择该版本。这解决了模糊性,因为C++规则规定最专业化的模板应该在不太专业化的模板上选择。

这是因为在推导参数时,一个模板对于第一个参数更好,而另一个模板更好。 让我们看看

促销

两位候选人都可以匹配。在第一个参数上,
Promotion
通过推断
T=Array
进行匹配<代码>促销
通过推断
T1=S来匹配。第二个是更好的匹配,因为
Array
T
更具体

在第二个参数上,
Promotion
是完全匹配的<代码>升级
通过推断
T2=S来匹配。由于
数组
数组
更匹配,因此第一个更具体

选择最佳模板的规则规定,与所有其他候选参数相比,一个参数必须更好地匹配,而所有其他参数不得更差。由于没有一位候选人符合这些标准,这是不明确的

第三个专门化确实满足标准(第一个参数与
数组
一样好,第二个是完美的),因此它解决了歧义


如果你真的想让自己头晕目眩,试着阅读《标准》中的[temp.Decrete.partial]一节,其中所有这些规则都以良好的语言表述。在草案n3225中是14.8.2.4,其他版本中的编号可能会有所不同。

也许您的困惑源于“比”更专业的关系如何运作。这是一个部分顺序,而不是全部顺序——这意味着给定两个模板专业化,并不总是一个比另一个更专业化

Anon的评论是正确的:假设第三专业化不存在,并且在代码的后面您有:

Promotion<Array<double>, Array<double> > foo;
这意味着:

Array<T1> = T
Array<T2> = T
意味着:

T = Array<T1>
T = Array<T2>
T=Array
T=阵列
因此答案也是否定的。给定任何类型的
T1
,总是可以找到一个类型
T
,这样
T
Array
的类型相同——只是字面上设置
T=Array
。但一般来说,另一种类型
T2
不受限制与
T1
相同,如果不是(例如,如果
T1=bool
T2=float
),则不可能找到与
Array
Array
相同的类型
T
。所以一般来说,不可能找到这样的类型
T

在这种情况下,两个专业都不比另一个专业更专业,甚至都不如另一个专业。因此,如果需要实例化此模板类,并且两个专业化匹配(正如Anon给出的示例所示),则无法选择“最佳”一个。

有问题,但作为一个具体示例,直接使用标准规则:

template< class T >
class Array {};

template< class T1, class T2 >
class Promotion {};

template <typename T>                   // a
class Promotion<T,T> {
public:
    typedef T ResultT;
};

template<typename T1, typename T2>      // b
class Promotion<Array<T1>, Array<T2> > {
public:
    typedef Array<typename Promotion<T1,T2>::ResultT> ResultT;
};

// template<typename T>
// class Promotion<Array<T>, Array<T> > {
//   public:
//     typedef Array<typename Promotion<T,T>::ResultT> ResultT;
// };


//---------------------------- §14.5.4.2/1:

template< class T >
void a_( Promotion< T, T > );                      // a

template< class T1, class T2 >
void b_( Promotion< Array< T1 >, Array< T2 > > );  // b


//---------------------------- §14.5.5.2/3:

class aT {};
class bT1 {};
class bT2 {};

void a( Promotion< aT, aT > );                          // a
void b( Promotion< Array< bT1 >, Array< bT2 > > );      // b

void test()
{
    // Check if the concrete 'a' arguments fit also 'b':
    b_( Promotion< aT, aT >() );
    // Fails, so a is not at least as specialized as b

    // Check if the concrete 'b' arguments fit also 'a':
    a_( Promotion< Array< bT1 >, Array< bT2 > >() );
    // Fails, so b is not at least as specialized as a
}    
模板
类数组{};
模板
班级晋升{};
模板//a
班级晋升{
公众:
类型定义T结果;
};
模板//b
班级晋升{
公众:
typedef数组结果;
};
//模板
//班级晋升{
//公众:
//typedef数组结果;
// };
//---------------------------- §14.5.4.2/1:
模板
无效(促销);//A.
模板
无效b_(升级,Array);//B
//---------------------------- §14.5.5.2/3:
在{}上课;
类bT1{};
bT2类{};
无效a(促销);//A.
无效b(促销,Array);//B
无效测试()
{
//检查具体的“a”参数是否也适合“b”:
b(晋升,晋升);;
//失败,因此a至少不如b专业化
//检查具体的“b”参数是否也适合“a”:
a(促销,Array>());
//失败,因此b至少不像a那么专业化
}    
免责声明:我不得不再次自学

我发这个是因为其他人™ 我觉得我的例子很有启发性,所以,可能对这里的读者也有帮助


干杯,

从概念层面上看专业化做了什么

第一种说法是“如果T1和T2是相同的,我们就应该这样做。”

第二个是“如果T1和T2都是数组模板,我们就应该这样做”

好吧,那么。。。假设T1和T2都是相同的数组模板。我们应该用哪一个?没有什么好办法可以证明其中一个更适合这种情况
T = Array<T1>
T = Array<T2>
template< class T >
class Array {};

template< class T1, class T2 >
class Promotion {};

template <typename T>                   // a
class Promotion<T,T> {
public:
    typedef T ResultT;
};

template<typename T1, typename T2>      // b
class Promotion<Array<T1>, Array<T2> > {
public:
    typedef Array<typename Promotion<T1,T2>::ResultT> ResultT;
};

// template<typename T>
// class Promotion<Array<T>, Array<T> > {
//   public:
//     typedef Array<typename Promotion<T,T>::ResultT> ResultT;
// };


//---------------------------- §14.5.4.2/1:

template< class T >
void a_( Promotion< T, T > );                      // a

template< class T1, class T2 >
void b_( Promotion< Array< T1 >, Array< T2 > > );  // b


//---------------------------- §14.5.5.2/3:

class aT {};
class bT1 {};
class bT2 {};

void a( Promotion< aT, aT > );                          // a
void b( Promotion< Array< bT1 >, Array< bT2 > > );      // b

void test()
{
    // Check if the concrete 'a' arguments fit also 'b':
    b_( Promotion< aT, aT >() );
    // Fails, so a is not at least as specialized as b

    // Check if the concrete 'b' arguments fit also 'a':
    a_( Promotion< Array< bT1 >, Array< bT2 > >() );
    // Fails, so b is not at least as specialized as a
}