The following code
#include <vector>
#include <string>
template<typename T>
struct V : public std::vector<T>
{
using Impl = std::vector<T>;
using typename Impl::vector; // the constructors
};
int main()
{
std::string empty;
V<std::string> meow{42UL, empty};
}
Is compiled fine by GCC 8.2 (calls the size_t, string
constructor).
However, clang up to 14 rejects it with
<source>:14:20: error: no matching constructor for initialization of 'V<std::string>' (aka 'V<basic_string<char>>')
V<std::string> meow{42UL, empty};
^ ~~~~~~~~~~~~~
<source>:5:8: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
struct V : public std::vector<T>
^
<source>:5:8: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
<source>:5:8: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided
as if V had no constructors: https://godbolt.org/z/M91zb6Pjr
Replacing using typename Impl::vector;
with using Impl::Impl;
makes clang accept the code. What is going on here?
using B::B
inside ofA
's class definition, whereA
is a derived class andB
is its base class. Where did you findusing typename B::vector;
form from? - The Dreams WindV
andvector
obviates the need. It's just somewhat less obvious due to how dependent names behave in templates.using V::vector::vector;
is standard and works in all compilers (well, that I tried on godbolt), without needing to specify all template arguments. - StoryTeller - Unslander Monica