简体   繁体   English

构造函数模板可以在类模板的c ++ 17参数推导中导致歧义

[英]Can constructor template cause ambiguity in the c++17 parameter deduction of class template

Consider a simple example: 考虑一个简单的例子:

template <class T>
struct foo {
    template <template <class> class TT>
    foo(TT<T>&&) {}
    foo(foo<T>&&){}
    foo() {}
};

int main() {
    foo      f1(foo<int>{}); //case 1.
    foo<int> f2(foo<int>{}); //case 2.
}

Case 1. causes ambiguity in the template argument deduction of foo class in clang but not in gcc. 情况1.在clang中的foo类的模板参数推导中导致模糊,但在gcc中没有。 I thought that template functions (here - constructor) have lower priority in overload resolution. 我认为模板函数(这里 - 构造函数)在重载决策中具有较低的优先级。 Is it not the case here? 这不是这种情况吗?

Error message: 错误信息:

prog.cc:10:14: error: ambiguous deduction for template arguments of 'foo'
    foo      f1(foo<int>{}); //case 1.
             ^
prog.cc:4:5: note: candidate function [with T = int, TT = foo]
    foo(TT<T>&&) {}
    ^
prog.cc:5:5: note: candidate function [with T = int]
    foo(foo<T>&&){}
    ^
1 error generated.

[clang demo] [gcc demo] [铿锵演示] [gcc演示]

This is a Clang bug. 这是一个Clang错误。 The fact the candidate set is formed from c'tors should be immaterial, since after the candidate set is formed the best overload is chosen using the same rules for ordering implicit conversion sequences and template function ordering. 候选集由c'tors组成的事实应该是无关紧要的,因为在形成候选集之后,使用相同的规则来选择最佳重载以用于排序隐式转换序列和模板函数排序。

To quote [over.match.funcs]/1 : 引用[over.match.funcs] / 1

The subclauses of [over.match.funcs] describe the set of candidate functions and the argument list submitted to overload resolution in each of the seven contexts in which overload resolution is used. [over.match.funcs]的子条款描述了在使用重载决策的七个上下文中的每个上下文中提交给重载决策的候选函数集和参数列表。 The source transformations and constructions defined in these subclauses are only for the purpose of describing the overload resolution process. 这些子条款中定义的源转换和构造仅用于描述重载解析过程。 An implementation is not required to use such transformations and constructions. 使用这种转换和构造不需要实现。

This clearly states that the overload resolution process is the same always. 这清楚地表明过载解决过程始终是相同的。 The only difference is how the candidate set is formed. 唯一的区别是候选集的形成方式。

And as specified by [over.match.class.deduct]/1 并由[over.match.class.deduct] / 1指定

A set of functions and function templates is formed comprising: 形成一组功能和功能模板,包括:

  • For each constructor of the primary class template designated by the template-name, if the template is defined, a function template with the following properties: 对于template-name指定的主类模板的每个构造函数,如果定义了模板,则具有以下属性的函数模板:

    • The template parameters are the template parameters of the class template followed by the template parameters (including default template arguments) of the constructor, if any. 模板参数是类模板的模板参数,后跟构造函数的模板参数(包括默认模板参数)(如果有)。

    • The types of the function parameters are those of the constructor. 函数参数的类型是构造函数的类型。

    • The return type is the class template specialization designated by the template-name and template arguments corresponding to the template parameters obtained from the class template. 返回类型是由模板名称和模板参数指定的类模板特化,其对应于从类模板获得的模板参数。

Each c'tor will introduce a pseudo function into the candidate set. 每个c'tor将伪函数引入候选集。 Like this: 像这样:

template <class T>                           foo(foo<T>&&) -> foo<T> 
template <class T, template<class> class TT> foo(TT<T>&&) -> foo<T> 

To illustrate further, if this was a free function bar : 为了进一步说明,如果这是一个免费功能bar

template <template <class> class TT, class T>
void bar(TT<T>&&) {}

template <class T>
void bar(foo<T>&&){}

Then template function ordering would place the first overload lower than the second. 然后模板函数排序会使第一个过载低于第二个过载。

They do not have lower priority. 它们没有较低的优先级。 You can solve the problem using SFINEA. 您可以使用SFINEA解决问题。 This is described in Effective Modern C++ from Scott Meyers. 这在Scott Meyers的Effective Modern C ++中有所描述。

template <class T>
struct foo {
    template <template <class> class TT, class =  std::enable_if_t<!std::is_same_v<foo<T>, std::decay_t<TT<T>>>>>
    foo(TT<T>&&) {}
    foo(foo<T>&&){}
    foo() {}
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM