Reputation: 197
Is it possible to write a deduction guide so that an instance of Simple
can be declared without template arguments? I've tried but cannot get the correct form to extract the std::unique_ptr
element type.
//------------------------------------------------------------------------------
template< class T >
class Simple
{
public:
Simple( std::unique_ptr< T >& u ) :
u_( u )
{}
private:
std::unique_ptr< T >& u_;
};
class MyThing
{};
int main()
{
std::unique_ptr< MyThing > upSimple;
Simple( upSimple ); // error C2955: 'Simple': use of class template requires template argument list
}
Upvotes: 3
Views: 950
Reputation: 66200
Is it possible to write a deduction guide so that an instance of Simple can be declared without template arguments? I've tried but cannot get the correct form to extract the std::unique_ptr element type.
The problem is another.
The implicitly generated deduction guides are perfectly able to extract the correct type template parameter for Simple
.
As pointed by Rakete1111, this is a sort of "most vexing parse" problem.
Writing
Simple( upSimple );
your intention was to obtain the initialization of a unnamed temporary object of type Simple
(Simple<MyThing>
, thanks to new C++17 implicitly generated deduction guides) initialized with the object upSimple
.
Unfortunately the compiler (visual-c++, but the same with g++ and clang++) interpret it as the declaration of a new variable (observe that parentheses declaring C++ variables are superfluous but perfectly legal; with int (i);
you declare a variable i
of type int
) of name upSimple
and type Simple
.
This give an error because
(1) upSimple
is defined in the preceding line so we have a redeclaration of upSimple
(2) implicitly generated deduction guides are unable, without a constructor argument, to deduce the template argument T
for Simple
.
To avoid this ambiguity, and obtain the initialization of a Simple<MyThing>
object, you can save the value in a variable with
auto s = Simple(upSimple);
or also with
Simple s(upSimple);
so the compiler can't interpret the line as declaration of variable upSimple
anymore.
If you really want an unnamed temporary object, you can use uniform initialization (you can use braces instead of parentheses)
//.....V..........V
Simple { upSimple };
that can't be interpreted as variable declaration.
And, yes: also the imposition of the use of new C++17 standard (through /std:c++17
or -std=c++17
or whichever is required from specific compiler) can be useful.
Upvotes: 4