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

时间:2015-05-19 01:19:27

标签: c++ constructor implicit

TLDR :我有两个模板化的课程OuterInner。可以从Inner<X>隐式构建XOuter<Y>可以隐式构建YOuter<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) {}
};

考虑以下功能:

struct SomeType{};
Outer<Inner<SomeType>> DoSomethingFails() {
  SomeType value;
  return value;      
}

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

但如果我改为:

Outer<Inner<SomeType>> DoSomethingWorks() {
  SomeType value;
  return Inner<SomeType>(value);      
}

有效。期望DoSomethingFails有效是否合理?如果没有,为什么?代码是否可以DoSomethingFails的方式更改?

1 个答案:

答案 0 :(得分:6)

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

引用N3337,§12.3[class.conv]

  

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

     

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

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

Outer<Inner<SomeType>> DoSomethingWorks2() {
  SomeType value;
  return {std::move(value)};
}