7

目前,我的玩具类模板之一有两个看起来非常相似的构造函数:

optional(const T& x)
{
    construct(x);
}

optional(T&& x)
{
    construct(std::move(x));
}

我可以将它们组合成一个构造函数模板,还是会以某种方式改变语义?

template<typename U>
optional(U&& x)
{
    construct(std::forward<U>(x));
}
4

4 回答 4

4

模板化的构造函数永远不会(编译器认为是)复制构造函数,抱歉。

于 2011-09-12T13:18:21.773 回答
2

It changes the way traits such as std::is_constructible and std::is_convertible interact with optional. For example given:

class A {};

int main()
{
    std::cout << std::is_constructible<optional<A>, int>::value << '\n';
};

Your original code would print out:

0

But your new code will print out:

1

If this is undesirable, and you still want to go with your new code, you could enable_if it to restrict U to acceptable types.

The only other possible issue I see is if T can be a reference type (e.g. int&). In that case the second constructor of your original code looks suspicious as it would be passing in an rvalue, and you might be trying to bind that rvalue to a non-const lvalue reference (can't tell for sure). If T can never be a reference type, no need to worry about this.

于 2011-09-12T14:39:25.977 回答
1

哦,construct 不是构造函数,它是成员函数模板。

那么可能语义不同。您的原始重载集将左值引用传递给 const 或将右值引用传递给非 const。模板版本也可以将左值引用传递给非常量。(我忽略了对 const 的右值引用。)

尽管construct很可能被声明为接受U&&(否则您之前移动 a 的重载T将不起作用)并且在这种情况下应该处理非常量左值,或者被声明为接受U const&并且在这种情况下它是无害的。

于 2011-09-12T13:57:12.353 回答
0

假设您至少construct(const T& x)并且可能添加了construct(T&& x)定义,并且您的 type 对象U可以转换为 type 对象T,我认为您应该没问题...

  1. 类型的常量左值引用U将绑定到construct(const T& x)
  2. 类型的非常量左值引用U将绑定到construct(const T& x)
  3. 类型的临时 r-valueU将绑定到construct(T&& x)construct(const T& x)未定义 r-value 引用版本
  4. A constant r-value reference of type U will bind to construct(const T& x)
于 2011-09-12T14:03:22.460 回答