4

I have encountered the following technique that allows the construction of a wrapper object around T, but from objects of type U, if T is constructible from U:

template< typename T > struct S { template< typename U, typename = std::enable_if_t< std::is_constructible< T, U >::value > > explicit S (U&& arg) : value (arg) { } ... }; 

IIUC, the type U used in the is_constructible test can be different from the cv-qualified type of arg.
Is it possible that the SFINAE test could fail although the expression value(arg) is valid?

0

1 Answer 1

4

Is it possible that the SFINAE test could fail although the expression value(arg) is valid?

The way you wrote S: yes, it's possible.
It follows a minimal, (not) working example:

#include<type_traits> template< typename T > struct S { template< typename U , typename = std::enable_if_t<std::is_constructible< T, U >::value > > explicit S (U&& arg) : value{arg} {} T value; }; struct A {}; struct B { B(A &) {} }; int main() { S<B> s(A{}); } 

The code above doesn't compile, but it does compile if you comment out the following line:

, typename = std::enable_if_t<std::is_constructible< T, U >::value > 

The problem is that you are not forwarding the constructor parameter. Instead, you are using an lvalue reference to a variable of type rvalue reference to A (that is arg) as an argument for value.
B is not constructible from an rvalue reference to A and the sfinae expression fails (correctly), but you are not actually using such a reference to construct the parameter, so removing the sfinae expression it works.
In fact, B is constructible from an lvalue reference to A, that is what you are using when you write value{arg}.


You should rather write S as it follows:

#include<utility> // ... template< typename T > struct S { template< typename U , typename = std::enable_if_t<std::is_constructible< T, U >::value > > explicit S (U&& arg) : value (std::forward<U>(arg)) { } T value; }; 

Note the use of std::forward to actually forward the parameters with the right types.
This at least solves the above mentioned issue and it should give you the guarantees you were looking for.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.