class 层次结构中的 C++ 'using' 关键字,具有函数调用运算符和私有继承
C++ 'using' keyword in class hierarchy with function call operator and private inheritance
我偶然发现了一些我不太明白的东西。我有一个使用私有继承的 class 层次结构,其中每个 struct
都定义了不同的函数调用运算符。奇怪的是,来自最顶层 struct
的函数调用运算符在最派生的 struct
中可用,尽管 using
指令仅在第一个派生的 struct
中使用.但是,正如预期的那样,在那里无法访问常规函数 foo
。示例:
#include <string>
#include <vector>
#include <iostream>
struct A {
void foo() {}
void operator()(bool) {
std::cout << "bool\n";
}
};
struct B : private A {
using A::foo;
using A::operator();
void operator()(std::string) {}
};
struct C : private B {
using B::operator();
void operator()(std::vector<int>) {}
};
struct D : private C {
using C::operator();
void operator()(std::vector<double>) {}
};
int main() {
D d{};
d(false); // <-- works!
//d.foo(); // <-- error: ‘void A::foo()’ is private within this context
return 0;
}
我在尝试使用 C++17 之前的代码实现与 boost::apply_visitor
一起使用的 C++17 overload
对象时偶然发现了这一点。我使用递归继承解决了它,其中每个对象都引入其直接基 class 的函数调用运算符,如下所示:
template<typename T, typename... Ts>
struct visitor : private T, private visitor<Ts...> {
using T::operator();
using visitor<Ts...>::operator();
visitor(T func, Ts... tail) : T{ std::move(func) }, visitor<Ts...>{ std::move(tail)... } {}
};
template<typename T>
struct visitor<T> : private T {
using T::operator();
visitor(T func) : T{ std::move(func) } {}
};
template<typename... Ts>
visitor<Ts...> make_visitor(Ts&&... funcs) {
return visitor<Ts...>{ std::forward<Ts>(funcs)... };
}
我想了解为什么所有运算符在最派生的对象中都可用。这就是我想出上面例子的方式。编译器是 g++ 11.1.0.
谁能告诉我这是怎么回事?
正如其他人在评论中指出的那样,原来我的想法有误。 using
引入了 all 相应基础 class 中可用的运算符,包括由基础 class 本身导入的运算符,因此所有运算符都将在最底部的对象中可用。另一方面,foo
只是传给了B
。
我偶然发现了一些我不太明白的东西。我有一个使用私有继承的 class 层次结构,其中每个 struct
都定义了不同的函数调用运算符。奇怪的是,来自最顶层 struct
的函数调用运算符在最派生的 struct
中可用,尽管 using
指令仅在第一个派生的 struct
中使用.但是,正如预期的那样,在那里无法访问常规函数 foo
。示例:
#include <string>
#include <vector>
#include <iostream>
struct A {
void foo() {}
void operator()(bool) {
std::cout << "bool\n";
}
};
struct B : private A {
using A::foo;
using A::operator();
void operator()(std::string) {}
};
struct C : private B {
using B::operator();
void operator()(std::vector<int>) {}
};
struct D : private C {
using C::operator();
void operator()(std::vector<double>) {}
};
int main() {
D d{};
d(false); // <-- works!
//d.foo(); // <-- error: ‘void A::foo()’ is private within this context
return 0;
}
我在尝试使用 C++17 之前的代码实现与 boost::apply_visitor
一起使用的 C++17 overload
对象时偶然发现了这一点。我使用递归继承解决了它,其中每个对象都引入其直接基 class 的函数调用运算符,如下所示:
template<typename T, typename... Ts>
struct visitor : private T, private visitor<Ts...> {
using T::operator();
using visitor<Ts...>::operator();
visitor(T func, Ts... tail) : T{ std::move(func) }, visitor<Ts...>{ std::move(tail)... } {}
};
template<typename T>
struct visitor<T> : private T {
using T::operator();
visitor(T func) : T{ std::move(func) } {}
};
template<typename... Ts>
visitor<Ts...> make_visitor(Ts&&... funcs) {
return visitor<Ts...>{ std::forward<Ts>(funcs)... };
}
我想了解为什么所有运算符在最派生的对象中都可用。这就是我想出上面例子的方式。编译器是 g++ 11.1.0.
谁能告诉我这是怎么回事?
正如其他人在评论中指出的那样,原来我的想法有误。 using
引入了 all 相应基础 class 中可用的运算符,包括由基础 class 本身导入的运算符,因此所有运算符都将在最底部的对象中可用。另一方面,foo
只是传给了B
。