如果我将成员函数f
添加到派生类,这将隐藏基类f
的整个重载集
struct B2{
int f(int);
int f(float);
};
struct D: B2{
int f(std::string);
};
D b;
b.f(42); // fails to compile because int B2::f(int) is not available.
对此的标准解决方法是使用声明
struct D: B2 {
int f(std::string);
using B2::f;
};
在我的情况下,B是模板参数:
template <typename B>
struct D: B {
int f(std::string);
using B::f;
};
还有一个困难,即B
可能有或没有f
方法,并且基类中缺少f
会导致编译器错误。
struct B1 {
};
template <typename B>
struct D: B {
int f(std::string);
using B::f;
};
void test() {
D<B1> b; // error: no members matching 'B1::f' in 'struct B1'
}
类似于别名声明的模板显然不能用于using
声明:
#include <string>
#include <type_traits>
struct B1 {
};
template <typename B>
struct D: B {
int f(std::string);
template <typename = typename std::enable_if_t<std::is_same_v<B2, B>>>
using B::f;
};
void test() {
D<B1> b;
}
这导致
<source>:15:10: error: expected '=' before '::' token
using B::f;
^~
<source>:15:12: error: 'f' in namespace '::' does not name a type
using B::f;
所以,我的问题是,基于编译时已知的东西(在代码编写时未知),使using
声明出现/消失的推荐方法是什么? (即我正在考虑使用sfinae / std :: enable_if / if constexpr)。
PS:
我正在考虑在f
中使用可变参数化模板方法D
,该方法通常会重定向到基类f
,并专门介绍我想添加的一个选项。这也许比using
声明更好吗?