Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is typename required or not here?

Consider the code:

#include <memory>

template <class T, class Deleter = std::default_delete<T>>
class unique_ptr_wrapper: public std::unique_ptr<T, Deleter>
{
public:
    using typename std::unique_ptr<T, Deleter>::unique_ptr;
    operator T* () const {return this->get();}
};

int main()
{
    unique_ptr_wrapper<int> upw{new int{42}};
}

g++5.1 compiles it fine, although clang++ complains

error: typename is allowed for identifiers only

I agree that we don't have an identifier here, so probably typename is not required. But is it actually forbidden? Is the compiler required to at least emit a diagnostic?

EDIT The code is compiled fine without typename by both g++ and clang++.


UPDATE It seems to be a g++ bug, I reported it here.

like image 592
vsoftco Avatar asked Feb 10 '23 23:02

vsoftco


1 Answers

[class.inhctor]/p1, emphasis mine:

A using-declaration (7.3.3) that names a constructor implicitly declares a set of inheriting constructors.

A constructor is not a type.

[temp.res]/p3-4:

3 When a qualified-id is intended to refer to a type that is not a member of the current instantiation (14.6.2.1) and its nested-name-specifier refers to a dependent type, it shall be prefixed by the keyword typename, forming a typename-specifier. If the qualified-id in a typename-specifier does not denote a type, the program is ill-formed.

4 If a specialization of a template is instantiated for a set of template-arguments such that the qualified-id prefixed by typename does not denote a type, the specialization is ill-formed. The usual qualified name lookup (3.4.3) is used to find the qualified-id even in the presence of typename.

[class.qual]/p2:

In a lookup in which function names are not ignored and the nested-name-specifier nominates a class C:

  • if the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C (Clause 9), or

  • in a using-declaration (7.3.3) that is a member-declaration, if the name specified after the nested-name-specifier is the same as the identifier or the simple-template-id’s template-name in the last component of the nested-name-specifier,

the name is instead considered to name the constructor of class C.

Applying the "usual qualified name lookup" rules found in [class.qual], std::unique_ptr<T, Deleter>::unique_ptr names the constructor. It does not denote a type. Therefore, by the above quote from [temp.res], the program is ill-formed (with a diagnostic required).

In other words, this appears to be a GCC bug (though Clang's error message could use some improvement too).

like image 80
T.C. Avatar answered Feb 12 '23 13:02

T.C.