Issue
The following code compiles fine under GCC but fails in clang with the error:
no matching constructor for initialization of 'Bar'
The problem seems to be that clang thinks the template constructor of Foo is hidden or overwritten by the template constructor of Bar.
Is this a bug in clang or a non standardized feature in GCC?
How to fix this problem? I cannot change Foo since it is 3rd party.
#include <type_traits>
struct Foo {
Foo() = default;
template<typename T, std::enable_if_t<std::is_trivially_copyable_v<T>>* = nullptr>
Foo(T& object) {}
};
struct Bar : public Foo {
using Foo::Foo;
template<typename T, std::enable_if_t<!std::is_trivially_copyable_v<T>>* = nullptr>
Bar(T& object) {}
};
int main() {
int i;
Bar s{i};
}
https://gcc.godbolt.org/z/etvpvF
Solution
Clang is correct. [namespace.udecl]/14:
(emhpasis mine)
When a using-declarator brings declarations from a base class into a derived class, member functions and member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list, cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting). Such hidden or overridden declarations are excluded from the set of declarations introduced by the using-declarator.
That means, for this case, the inheriting constructor template from foo
is hidden from lookup by the constructor template from Bar
. Note that only name, parameter-type-list, cv-qualification, and ref-qualifier are considered in hiding, even for templates.
Answered By - songyuanyao