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

jot*_*tik 6 c++ gcc clang compiler-bug c++11

以下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');
}
Run Code Online (Sandbox Code Playgroud)

与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.
Run Code Online (Sandbox Code Playgroud)

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

lll*_*lll 6

我认为这是一个gcc bug.

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

[namespace.udecl]

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

...

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

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

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

  • 遗憾的是模板参数不是该列表的一部分: - / (5认同)