The union of two constructors that copy and move

There are currently two constructors in one of my toy patterns that look very similar:

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

Is it possible to combine them into one constructor template, or will this somehow change the semantics?

 template<typename U> optional(U&& x) { construct(std::forward<U>(x)); } 
+7
source share
4 answers

It changes the way it interacts with std::is_constructible and std::is_convertible with optional . For example:

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

Your source code will be printed:

 0 

But your new code will be printed:

 1 

If this is undesirable, and you still want to upgrade with the new code, you can enable_if limit it to U valid types.

The only other possible problem that I see is that T may be a reference type (e.g. int& ). In this case, the second constructor of the source code looks suspicious, because it will pass the value of r, and you can try to associate this value with a reference to the constant lvalue (you can’t say for sure). If T never be a reference type, no need to worry about that.

+2
source

The template constructor will never (considered by the compiler) the copy constructor, sorry.

+4
source

Oh, the construct is not a constructor; it is a member function template.

Then perhaps the semantics are different. Your source overload set passes either a lvalue reference to a constant, or an rvalue reference to a non-const. The template version can also pass an lvalue reference to non-const. (I ignore the rvalue references for const.)

Apparently, although construct declared as accepting U&& (otherwise your previous overload that moves T will not work), in which case it must deal with non-const lvalues ​​or is declared to accept U const& , in which case it harmless.

+1
source

Assuming you have at least construct(const T& x) and possibly added construct(T&& x) , and your object of type U can be converted to an object of type T , I think you should be fine ...

  • Permalink l-values ​​of type U will be bound to construct(const T& x)
  • A mutable reference of an l-value of type U will be bound to construct(const T& x)
  • A temporary value r of type U will be bound to construct(T&& x) or construct(const T& x) if the reference version of the r-value is not defined
  • Permalink r-values ​​of type U will be bound to construct(const T& x)
0
source

All Articles