Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructor instantiation in a world of guaranteed copy elision

Consider this example:

template <typename T>
using type = typename T::type;

template <typename T>
struct A
{
    A(type<T>);
};

A<int> f();
A<int> g() { return f(); }

Neither gcc nor clang compile this code due to int not having a nested type typedef. But why is that constructor being instantiated at all? f() is a prvalue of the same type as the return of g(), there shouldn't even be a move there. What is causing us to instantiate the bad constructor?

like image 280
Barry Avatar asked Jun 26 '18 13:06

Barry


People also ask

What is guaranteed copy elision?

One if these optimization techniques elides copies and moves by constructing an object directly into the target of the omitted cope/move operation. This technique is called copy/move elision and is now guaranteed by the C++17 standard to occur in certain situations.

What is a guaranteed copy?

Guaranteed copy elision redefines a number of C++ concepts, such that certain circumstances where copies/moves could be elided don't actually provoke a copy/move at all. The compiler isn't eliding a copy; the standard says that no such copying could ever happen. Consider this function: T Func() {return T();}


1 Answers

The constructor is a bit of a red herring. The same would happen if it was any other member function.

template <typename T>
struct A
{
    void foo(type<T>); // Same error
};

This is on account of [temp.inst]/2

The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, default arguments, or noexcept-specifiers of the class member functions, [...]

The declaration is instantiated, so type<T> has to be well-formed.

like image 106
StoryTeller - Unslander Monica Avatar answered Oct 09 '22 02:10

StoryTeller - Unslander Monica