Mar*_*rio 7 c++ language-lawyer
我偶然发现了这个奇怪的名称查找问题,其中基类成员函数似乎根本不参与重载选择,即使它是使用using语句导入的.基类和派生类的成员函数都是SFINAE'd enable_if_t.
我能够使用以下代码重现我的问题:https://gcc.godbolt.org/z/ueQ-kY
#include <iostream>
#include <type_traits>
class MyTag {};
struct Base
{
template <typename RType>
std::enable_if_t<std::is_convertible<RType, int>::value> create(RType /*&&*/ ref)
{
std::cout << "Base::create(RType ref)" << std::endl;
}
};
struct Derived : Base
{
using Base::create;
template <typename Tag>
std::enable_if_t<std::is_same<Tag, MyTag>::value> create(Tag /*&&*/ tag)
{
std::cout << "Derived::create(Tag tag)" << std::endl;
}
};
int main()
{
Derived d;
d.create(MyTag());
d.create(0); // [x86-64 clang 7.0.0 #1] error: no matching member function for call to 'create'
}
Run Code Online (Sandbox Code Playgroud)
虽然GCC在没有警告的情况下编译上面的代码,但clang,icc和MSVC无法为调用d.create(0);和错误构建找到合适的重载.事实上,从错误消息判断,似乎Base::create甚至没有参与重载决议.
但是,当两个成员函数中的一个将其参数作为转发引用时,代码在所有主要编译器上编译良好.
Gcc错了,应该拒绝你的例子.
Run Code Online (Sandbox Code Playgroud)using-declaration: using using-declarator-list ;
[namespace.udecl]/1每个使用说明符在一个using声明引入了一组声明到其中所述声明性区域使用声明出现.该组通过引入的声明用声明符通过进行合格名称查找发现(
[basic.lookup.qual],[class.member.lookup]在用于名称)使用说明符,不包括如下所述隐藏功能.
排除的功能是:
[namespace.udecl]/15当using-declarator将基类的声明带入派生类时,派生类中的成员函数和成员函数模板覆盖和/或隐藏具有相同名称的成员函数和成员函数模板,parameter-type-list,cv-基类中的限定和ref限定符(如果有)(而不是冲突).这些隐藏或重写的声明被排除在using-declarator引入的声明集之外.
但是,当两个成员函数中的一个将其参数作为通用引用时,代码在所有主要编译器上编译良好.
当其中一个函数将其参数作为(转发)引用时,此模板函数不再被限定为隐藏,因为其参数类型列表不同.
OP打开了一个错误报告,检查出来:
错误87478 - 隐藏成员函数错误地参与限定名称查找.
| 归档时间: |
|
| 查看次数: |
118 次 |
| 最近记录: |