SFINAE 方法在 clang 中完全禁用基类的模板方法
SFINAE method completely disables base class's template method in clang
#include <iostream>
#include <utility>
struct B {
template<typename T, std::enable_if_t<std::is_same<T, int>::value>* = nullptr>
void foo(T) {
std::cout<<"B::foo"<<std::endl;
}
};
struct D: B {
using B::foo;
template<typename T, std::enable_if_t<std::is_same<T, std::string>::value>* = nullptr>
void foo(T) {
std::cout<<"D::foo"<<std::endl;
}
};
int main() {
D d;
d.foo(2); // gcc: print "B::foo"; clang: compile error
return 0;
}
假设我们想在派生类 D 中公开foo()
重载.gcc 和 Visual Studio 编译并打印"B::foo",正如我预期的那样。但是我收到一个编译错误:
prog.cc:22:7: error: no matching member function for call to 'foo'
d.foo(2);
~~^~~
prog.cc:14:10: note: candidate template ignored: requirement 'std::is_same<int, std::string>::value' was not satisfied [with T = int]
void foo(T) {
这是叮当虫吗?谢谢!
我实际上认为这是一个gcc错误(84832密切相关,尽管正如Wakely指出的那样,这可能是一个核心语言问题(。
从 [namespace.udecl]/15:
当using-declarator将基类中的声明引入派生类时,派生类中的成员函数和成员函数模板将覆盖和/或隐藏基类中具有相同名称、参数类型列表、cv 限定符和ref 限定符(如果有(的成员函数和成员函数模板(而不是冲突(。此类隐藏或重写的声明将从using-声明符引入的声明集中排除。
在 [dcl/fct]/5 中定义参数类型列表的地方:
函数的类型使用以下规则确定。每个参数(包括函数参数包(的类型由其自己的decl-specifier-seq和声明符确定。确定每个参数的类型后,任何类型为"T 数组"或函数类型 T 的参数都将调整为"指向 T 的指针"。生成参数类型列表后,在形成函数类型时,将删除任何修改参数类型的顶级cv 限定符。转换后的参数类型的结果列表以及省略号或函数参数包的存在与否是函数的参数类型列表。
B::foo
和D::foo
具有相同的名称("foo"(,参数类型列表([T]
(,cv限定符(none(和ref限定符(none(。因此,派生的隐藏了基础的。
如果有人正在寻找解决此问题的方法,您可以在辅助结构中定义额外的重载,然后乘以继承:
#include <iostream>
#include <utility>
struct B {
template<typename T, std::enable_if_t<std::is_same<T, int>::value>* = nullptr>
void foo(T) {
std::cout<<"B::foo"<<std::endl;
}
};
struct C {
template<typename T, std::enable_if_t<std::is_same<T, std::string>::value>* = nullptr>
void foo(T) {
std::cout<<"C::foo"<<std::endl;
}
};
struct D: B, C {
using B::foo;
using C::foo;
};
int main() {
D d;
d.foo(2); // prints B::foo
return 0;
}
相关文章:
- 公开最直接的基类模板名称
- 通过基类接受方法转发派生 UniquePtr 的右值会移动引用而不是复制
- 引用基类模板的成员变量的简单方法
- C++初始化之前派生类调用基类的方法
- 为什么派生类的实例从基类调用方法?
- 为什么允许将派生类的方法static_cast为基类的方法?
- 使用基类模板检测is_base_of
- 我无法重写基类的方法,因为我的派生类是模板化的
- 是否可以从构造函数自动推断基类模板参数?
- C++继承,如何在基类的方法中调用子类的方法?
- 指向类模板方法的 void 指针的向量
- C ++中有没有办法让派生类重写基类静态方法
- 通过派生类模板参数指定基类模板参数之一。如何使用基类的 using 声明
- 将指针从派生到基类的方法的最佳方法
- C 错误:从(基类模板)到子类的无效转换
- 在C++中调用基类模板构造函数
- 不能使用基类模板成员函数
- 从基类模板化虚拟方法,而不是使用重载
- 我可以在基类模板方法中自动推导子类型吗
- 用基类模板化的静态方法(aka.Factory)派生类