通过两个隐式构造函数构造一个值?

don*_*uri 3 c++ constructor implicit

TLDR:我有两个模板化类OuterInner.Inner<X>可以隐式构造X,Outer<Y>也可以隐式构造Y.应该Outer<Inner<X>> = X()工作?

更多细节:

假设我有以下两个类:

template<typename T> 
class Inner {
  public: 
    Inner(const T& value) {}
    Inner(T&& value) {}
};

template<typename T>
class Outer {
  public:
    Outer(const T& value) {}
    Outer(T&& value) {}
};
Run Code Online (Sandbox Code Playgroud)

考虑以下功能:

struct SomeType{};
Outer<Inner<SomeType>> DoSomethingFails() {
  SomeType value;
  return value;      
}
Run Code Online (Sandbox Code Playgroud)

g ++抱怨:

no viable conversion from 'SomeType' to 'Outer<Inner<SomeType> >'
note: candidate constructor not viable: no known conversion from 'SomeType' to 'const Inner<SomeType> &' for 1st argument
Run Code Online (Sandbox Code Playgroud)

但如果我改为:

Outer<Inner<SomeType>> DoSomethingWorks() {
  SomeType value;
  return Inner<SomeType>(value);      
}
Run Code Online (Sandbox Code Playgroud)

有用.期望DoSomethingFails工作是否合理?如果没有,为什么?并且可以以有效的方式更改代码DoSomethingFails吗?

Pra*_*ian 6

您的第一个示例需要两个用户定义的转换才能编译 - SomeType -> Inner -> Outer.但是,最多可以隐式应用一个用户定义的转换.

引用N3337,§12.3[class.conv]

1类对象的类型转换可以由构造函数和转换函数指定.这些转换称为用户定义的转换,用于隐式类型转换(第4节),初始化(8.5)和显式类型转换(5.4,5.2.9).

4最多只有一个用户定义的转换(构造函数或转换函数)隐式应用于单个值.


如果目标是避免Inner<SomeType>在return语句中提及,则可以使用列表初始化.

Outer<Inner<SomeType>> DoSomethingWorks2() {
  SomeType value;
  return {std::move(value)};
}
Run Code Online (Sandbox Code Playgroud)