构造函数SFINAE和继承在clang中失败

以下代码在GCC下可以正常编译,但在clang中失败并显示错误:

  

没有匹配的构造函数,用于初始化“ Bar”

问题似乎是clang认为 Foo 的模板构造函数被 Bar 的模板构造函数隐藏或覆盖。

这是Clang中的错误还是GCC中的非标准化功能?

如何解决此问题?因为它是第三方,所以我不能更改Foo。

#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

yy2626 回答:构造函数SFINAE和继承在clang中失败

C语是正确的。 [namespace.udecl]/14

(肺hp矿)

  

当using-declarator将基类中的声明带入   派生类,成员函数和成员函数模板   派生类重写和/或隐藏成员函数和成员   具有相同名称,parameter-type-list,   基本类别中的cv-qualification和ref-qualifier(如果有)   而不是冲突。此类隐藏或覆盖的声明不包括在内   来自using-declarator引入的一组声明。

这意味着,在这种情况下,foo的继承构造函数模板被Bar的构造函数模板隐藏。请注意,即使是模板,也只考虑名称,parameter-type-list,cv-qualification和ref-qualifier。

, 添加第二个模板参数和默认参数后,

Clang不会继承构造函数模板。另一方面,在函数的参数列表(C ++ 03样式)中使用SFINAE构造没有问题:

struct Foo {
    Foo() = default;

    template<typename T>
    Foo(T& object,std::enable_if_t<std::is_trivially_copyable_v<T>>* = nullptr) {}
};

struct Bar : public Foo {
    using Foo::Foo;

    template<typename T>
    Bar(T& object,std::enable_if_t<!std::is_trivially_copyable_v<T>>* = nullptr) {}
};

Live example

在此版本中,构造函数模板可以很好地继承,并可以像预期的那样用于重载解析。


将自己的SFINAE检查移到c'tor的参数中,而不更改Foo似乎也可以解决该问题:

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>
    Bar(T& object,std::enable_if_t<!std::is_trivially_copyable_v<T>>* = nullptr) {}
};

Live example

Clang认为原始模板的签名与基类中的签名相同。因此,它认为隐藏了基类版本。

本文链接:https://www.f2er.com/3161764.html

大家都在问