C++:使用声明和重载范例
C++: using declaration and overload paradigm
我正在查看 this page 关于 C++17 的“新”特性。
特别是我几乎理解以下所有代码:
#include <iostream>
#include <variant>
struct Fluid { };
struct LightItem { };
struct HeavyItem { };
struct FragileItem { };
template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
template<class... Ts> overload(Ts...) -> overload<Ts...>;
int main() {
std::variant<Fluid, LightItem, HeavyItem, FragileItem> package;
std::visit(overload{
[](Fluid& ) { std::cout << "fluid\n"; },
[](LightItem& ) { std::cout << "light item\n"; },
[](HeavyItem& ) { std::cout << "heavy item\n"; },
[](FragileItem& ) { std::cout << "fragile\n"; }
}, package);
}
我做的不是理解的是
using Ts::operator()...;
在结构 overload
的定义中。据我所知,这样使用 using
关键字是为了确保 operator()
成为 public
。但就涉及 lambda 而言,在我看来已经 public。所以我会说这是多余的。我尝试用
编译和执行
template<class... Ts> struct overload : Ts... { };
一切正常。我错了吗?我错过了什么吗?
using
目的不仅是为了改变可访问性,而且是为了“解决”歧义 and/or 取消隐藏基本方法。
见
https://en.cppreference.com/w/cpp/language/unqualified_lookup#Member_function_definition
otherwise, if the declaration sets in Bi and in C are different, the result is an ambiguous merge: the new lookup set of C has an invalid declaration and a union of the subobjects ealier merged into C and introduced from Bi. This invalid lookup set may not be an error if it is discarded later.
struct Base1
{
void foo() {}
};
struct Base2
{
void foo(int) {}
};
struct D : Base1, Base2
{
// using Base1::foo; // Those would solve the ambiguity
// using Base2::foo;
void bar()
{
foo(); // ambiguous
}
}
struct D2 : Base1
{
// using Base1::foo; // This would unhide Base1::foo
void foo(char) {} // hides Base1::foo
void bar()
{
foo(); // wrong, find D2::foo(char)
}
}
using Ts::operator()...;
就是可变参数语法。
我正在查看 this page 关于 C++17 的“新”特性。 特别是我几乎理解以下所有代码:
#include <iostream>
#include <variant>
struct Fluid { };
struct LightItem { };
struct HeavyItem { };
struct FragileItem { };
template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
template<class... Ts> overload(Ts...) -> overload<Ts...>;
int main() {
std::variant<Fluid, LightItem, HeavyItem, FragileItem> package;
std::visit(overload{
[](Fluid& ) { std::cout << "fluid\n"; },
[](LightItem& ) { std::cout << "light item\n"; },
[](HeavyItem& ) { std::cout << "heavy item\n"; },
[](FragileItem& ) { std::cout << "fragile\n"; }
}, package);
}
我做的不是理解的是
using Ts::operator()...;
在结构 overload
的定义中。据我所知,这样使用 using
关键字是为了确保 operator()
成为 public
。但就涉及 lambda 而言,在我看来已经 public。所以我会说这是多余的。我尝试用
template<class... Ts> struct overload : Ts... { };
一切正常。我错了吗?我错过了什么吗?
using
目的不仅是为了改变可访问性,而且是为了“解决”歧义 and/or 取消隐藏基本方法。
见 https://en.cppreference.com/w/cpp/language/unqualified_lookup#Member_function_definition
otherwise, if the declaration sets in Bi and in C are different, the result is an ambiguous merge: the new lookup set of C has an invalid declaration and a union of the subobjects ealier merged into C and introduced from Bi. This invalid lookup set may not be an error if it is discarded later.
struct Base1
{
void foo() {}
};
struct Base2
{
void foo(int) {}
};
struct D : Base1, Base2
{
// using Base1::foo; // Those would solve the ambiguity
// using Base2::foo;
void bar()
{
foo(); // ambiguous
}
}
struct D2 : Base1
{
// using Base1::foo; // This would unhide Base1::foo
void foo(char) {} // hides Base1::foo
void bar()
{
foo(); // wrong, find D2::foo(char)
}
}
using Ts::operator()...;
就是可变参数语法。