Oli*_*liv 6 c++ constraints using-declaration language-lawyer c++20
让我们考虑下面的代码,其中base成员在derived类中声明。GCC 和 Clang 不同意隐藏哪个成员:
template <class T>
concept C = true;
struct base
{
template <class T>
void foo0 (T&&);
template <class T>
void foo1(T&&) requires C<T>;
template <C T>
void foo2(T&&);
void foo3(C auto &&);
template <C T, class U>
void foo4(T&&, U&&);
template <C T, class U>
void foo5(T&&, U&&);
};
struct derived
: base
{
using base::foo0;
using base::foo1;
using base::foo2;
using base::foo3;
using base::foo4;
using base::foo5;
template <class T>
void foo0(T&&);
template <class T>
void foo1(T&&);
template <class T>
void foo2(T&&);
void foo3(auto &&);
template <class T, class U>
void foo4(T&&, U&&);
template <class T, class U> //inversed template parmeter order
void foo5(U&&, T&&);
};
Run Code Online (Sandbox Code Playgroud)
当derived成员函数调用,GCC和锵并不总是同意其功能应该被称为:(编译探险链接)
void g(derived d, int i) // Description of the difference
{//Function called | by GCC | by Clang | between base and derived member
// -----------------------------------------
d. foo0(i); // | derived | derived | same signature
d. foo1(i); // | base | base | trailing require clause
d. foo2(i); // | base | derived | constrained template parameter
d. foo3(i); // | base | derived | constrained function parameter
d. foo4(i,i); // | base | derived | constrained template parameter
d. foo5(i,i); // | base | base | reversed template parameter order
// with constraint.
}
Run Code Online (Sandbox Code Playgroud)
从道德上讲,我不明白foo1 foo2,foo3应该是不同的情况。
哪个编译器是对的?
指定是否隐藏基成员声明的标准段落是[namespace.udecl]/14:
当 using 声明器将基类的声明引入派生类时,派生类中的成员函数和成员函数模板将覆盖和/或隐藏具有相同名称的成员函数和成员函数模板,参数类型列表 ([dcl .fct])、尾随 requires 子句(如果有)、cv 限定符和 ref 限定符(如果有),在基类中(而不是冲突)。这种隐藏或覆盖的声明被排除在 using-declarator 引入的声明集中。
在第一次阅读之后,看起来 Clang 正在应用这封信的标准。但...
但是这里的字母是什么意思?没有模板头的模板的等效参数类型列表是什么意思?考虑 的情况foo5,很明显 Clang 考虑了模板头,至少是模板参数顺序。