函数模板修改用顶级const:clang bug声明的参数?

Nic*_*ick 8 c++ clang c++11 c++14

下面的代码clang 3.8.1-1在ArchLinux上正确编译.

这个clang错误吗?

gcc 在此发出正确的警告/错误.

template <class T>
struct BugReproducer{
    using size_type = typename T::size_type;

    int bug1(size_type count);
    int bug2(size_type count) const;
    static int bug3(size_type count);
};

template <class T>
int BugReproducer<T>::bug1(size_type const count){
    // this is a bug. must be not allowed
    count = 5;

    // return is to use the result...
    return count;
}

template <class T>
int BugReproducer<T>::bug2(size_type const count) const{
    // same for const method
    count = 5;
    return count;
}

template <class T>
int BugReproducer<T>::bug3(size_type const count){
    // same for static method
    count = 5;
    return count;
}



struct DummyVector{
    using size_type = int;
};



int main(){
    using BugRepr = BugReproducer<DummyVector>;

    BugRepr reproducer;

    auto a = reproducer.bug1(1);
    auto b = reproducer.bug2(1);
    auto c = BugRepr::bug3(1);

    // return is to use the result...
    return a + b + c;
}
Run Code Online (Sandbox Code Playgroud)

我在这里如何编译:

[nmmm@zenbook HM3]$ clang x.cc -std=c++11 -lstdc++ -Wall -Wpedantic -Wconversion
Run Code Online (Sandbox Code Playgroud)

clangc++14- 相同的结果.

[nmmm@zenbook HM3]$ clang x.cc -std=c++14 -lstdc++ -Wall -Wpedantic -Wconversion
Run Code Online (Sandbox Code Playgroud)

这是gcc输出:

[nmmm@zenbook HM3]$ gcc x.cc -std=c++11 -lstdc++ -Wall -Wpedantic -Wconversion
x.cc: In instantiation of ‘int BugReproducer<T>::bug1(BugReproducer<T>::size_type) [with T = DummyVector; BugReproducer<T>::size_type = int]’:
x.cc:46:28:   required from here
x.cc:13:8: error: assignment of read-only parameter ‘count’
  count = 5;
  ~~~~~~^~~
x.cc: In instantiation of ‘int BugReproducer<T>::bug2(BugReproducer<T>::size_type) const [with T = DummyVector; BugReproducer<T>::size_type = int]’:
x.cc:47:28:   required from here
x.cc:22:8: error: assignment of read-only parameter ‘count’
  count = 5;
  ~~~~~~^~~
x.cc: In instantiation of ‘static int BugReproducer<T>::bug3(BugReproducer<T>::size_type) [with T = DummyVector; BugReproducer<T>::size_type = int]’:
x.cc:48:20:   required from here
x.cc:29:8: error: assignment of read-only parameter ‘count’
  count = 5;
  ~~~~~~^~~
Run Code Online (Sandbox Code Playgroud)

eca*_*mur 5

是的,这是铿锵的错误; 提交自https://llvm.org/bugs/show_bug.cgi?id=30365.

错误的本质是在类模板成员函数定义出现在外部([class.mfct]/1)类模板,参数类型依赖于类模板参数,clang使用声明的参数类型而不是在最顶层的cv-qualification中它们不同的定义的参数类型.简化示例:

template<class T> struct A { void f(typename T::U); };
template<class T> void A<T>::f(typename T::U const i) { i = 1; }
struct X { using U = int; };
int main() { A<X>{}.f(0); }
Run Code Online (Sandbox Code Playgroud)

Per [dcl.fct]/5 i定义中的类型A<X>::fint const(对于函数参数使用'const'):

5 - [...]生成参数类型列表后,在形成函数类型时,将删除修改参数类型的任何顶级cv限定符.[...] [ 注意:此转换不会影响参数的类型.[...] - 结束说明 ]