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.
[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 oftypename
.
[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 ofC
(Clause 9), orin 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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With