Clang无法从基类中找到const模板成员函数

时间:2018-03-12 12:20:54

标签: c++ c++11 gcc clang compiler-bug

以下C ++文件:

struct Base {
    template <typename T, int = 42>
    void f(T &&) const {}
};

struct Derived: Base {
    template <typename T, typename X = typename T::asdf>
    void f(T &&) const {}

    using Base::f;
};

int main() {
    Derived const cd;
    cd.f('x');
}

与GCC汇编良好,但不与Clang汇总:

$ g++-7.3.0 -std=c++11 test.cpp -o test -Wall -Wextra
$ g++-7.2.0 -std=c++11 test.cpp -o test -Wall -Wextra
$ g++-6.4.0 -std=c++11 test.cpp -o test -Wall -Wextra
$ g++-5.4.0 -std=c++11 test.cpp -o test -Wall -Wextra
$ g++-4.9.4 -std=c++11 test.cpp -o test -Wall -Wextra
$ clang++-4.0 -std=c++11 test.cpp -o test -Wall -Wextra
test.cpp:15:12: error: no matching member function for call to 'f'
        cd.f('x');
        ~~~^
test.cpp:8:14: note: candidate template ignored: substitution failure [with T = char]: type 'char' cannot be used prior to '::' because it has no members
        void f(T &&) const {}
            ^
1 error generated.
$ clang++-5.0 -std=c++11 test.cpp -o test -Wall -Wextra
test.cpp:15:12: error: no matching member function for call to 'f'
        cd.f('x');
        ~~~^
test.cpp:8:14: note: candidate template ignored: substitution failure [with T = char]: type 'char' cannot be used prior to '::' because it has no members
        void f(T &&) const {}
            ^
1 error generated.
$ clang++-6.0 -std=c++11 test.cpp -o test -Wall -Wextra
test.cpp:15:12: error: no matching member function for call to 'f'
        cd.f('x');
        ~~~^
test.cpp:8:14: note: candidate template ignored: substitution failure [with T = char]: type 'char' cannot be used prior to '::' because it has no members
        void f(T &&) const {}
            ^
1 error generated.

为什么不用Clang编译?我的代码是否正确?这是编译器错误吗? C ++标准中的一个错误?

1 个答案:

答案 0 :(得分:6)

我认为这是一个gcc bug。

根据using-declarator(强调我的):

[namespace.udecl]

  

using-declarator引入的声明集是通过对using-declarator中的名称执行限定名查找([basic.lookup.qual],[class.member.lookup])来找到的,不包括函数隐藏如下所述。

     

...

     

当using-declarator将基类的声明带入派生类时,派生类中的成员函数和成员函数模板覆盖和/或隐藏成员函数和成员函数模板,其名称相同,参数 - 基类中的type-list,cv-qualification和ref-qualifier(如果有的话)(而不是冲突)。这些隐藏或重写的声明被排除在using-declarator引入的声明集之外。

在您的情况下,基类f()应该被隐藏,并且对派生类是不可见的。

另一个重点是,using的效果是在SFINAE之前的名称查找阶段。因此,是否存在SFINAE没有影响。