C++ 在C+代码中,`operator()…`是什么意思+;?
我试图理解std::visit的示例,在这里我看到了以下代码行:C++ 在C+代码中,`operator()…`是什么意思+;?,c++,templates,operator-keyword,c++17,variant,C++,Templates,Operator Keyword,C++17,Variant,我试图理解std::visit的示例,在这里我看到了以下代码行: template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; 模板结构重载:Ts。。。{使用Ts::运算符()…;}; 模板重载(Ts…)->重载; 我不明白。opera
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
模板结构重载:Ts。。。{使用Ts::运算符()…;};
模板重载(Ts…)->重载;
我不明白。operator()…
在代码中是什么意思 这里的语法是…
在您的特定情况下,以下是如何为一个、两个和三个参数扩展重载结构:
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<typename A, typename B>
struct overloaded: A, B
{
using A::operator(); using B::operator();
};
template<typename A, typename B, typename C>
struct overloaded: A, B, C
{
using A::operator(); using B::operator(); using C::operator();
};
模板结构重载:Ts。。。{使用Ts::运算符()…;};
一个论点:
template <class A> struct overloaded : A { using A::operator(); };
模板结构重载:A{using A::operator();};
两个论点:
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<typename A, typename B>
struct overloaded: A, B
{
using A::operator(); using B::operator();
};
template<typename A, typename B, typename C>
struct overloaded: A, B, C
{
using A::operator(); using B::operator(); using C::operator();
};
模板
结构重载:A,B
{
使用A::operator();使用B::operator();
};
三个论点:
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<typename A, typename B>
struct overloaded: A, B
{
using A::operator(); using B::operator();
};
template<typename A, typename B, typename C>
struct overloaded: A, B, C
{
using A::operator(); using B::operator(); using C::operator();
};
模板
结构重载:A、B、C
{
使用A::operator();使用B::operator();使用C::operator();
};
使用Ts::operator()理解代码>,首先您必须知道类。。。Ts
是(可变模板的)参数包。这是一个0的序列。。。N模板类型参数
使用Ts::operator()…
中的省略号是参数包扩展的语法。例如,在重载的情况下,使用Ts::operator()代码>声明将扩展为等效于:
using Foo::operator();
using Bar::operator();
我想用一点历史课来补充这些伟大的答案
这里有很多层,所以让我们把它们一层一层地剥开
- 可变模板(C++11)
- 参数包
- 包扩展
- 使用
声明的
用于介绍基类成员
变量使用
声明(C++17)
模板演绎指南(C++17)
可变模板
在C++11之前,我们限制了一个函数可以接收的模板参数的数量,这取决于程序员愿意键入多少
例如,如果我想编写一个函数来汇总潜在不同类型的“任意”数量的值,我需要编写大量的样板文件,尽管如此,我还是受到了限制:
template<class T>
void foo(T){}
template<class T, class U>
void foo(T, U){}
template<class T, class U, class V>
void foo(T, U, V){}
// ... and so on until I decide enough's enough
可以这样想:
int a = /*...*/;
double b = /*...*/;
char c = /*...*/;
foo(a, b, c);
template<int, double, char>
void foo(Arguments[3] args){}
template<class T, class U>
struct derived : T, U
{
using T::do_a_thing;
using U::do_a_thing;
};
int main(){
derived<does_a_thing, also_does_a_thing> d;
d.do_a_thing(1); // calls also_does_a_thing::do_a_thing
}
std::vector<int> vec{1, 2, 3};
IteratorWrapper iter_wrapper(vec);
std::list<double> lst{4.1, 5.2};
IteratorWrapper lst_wrapper(lst);
声明一个类重载
,该类可以在“无限”数量的类型上进行模板化
它的:Ts.
部分:
template<class... Ts> struct overloaded : Ts...
在C++11中,我们收到了使用
语句的,该语句可以做同样的事情,可能更清楚一点(还有更多!请稍候)
然而,using
语句最初用于不同的用途(自从引入C++11以来,它的用法已经大大扩展)。创建它的主要原因之一是,我们可以在派生类中重用基类中的内容,而无需强制客户端消除歧义:
不使用使用
struct does_a_thing
{
void do_a_thing(double){}
};
struct also_does_a_thing
{
void do_a_thing(int){}
};
struct derived : does_a_thing, also_does_a_thing{};
int main(){
derived d;
d.do_a_thing(1); // ? which "do_a_thing gets called? Neither, because it's ambiguous, so there's a compiler error
d.does_a_thing::do_a_thing(42.0);
d.also_does_a_thing::do_a_thing(1);
}
请注意,客户端被迫编写一些时髦的语法,以引用他们希望用于调用do\u thing
的derived
的基。如果我们利用使用
,这看起来会更好:
struct derived : does_a_thing, also_does_a_thing
{
using does_a_thing::do_a_thing;
using also_does_a_thing::do_a_thing;
};
int main(){
derived d;
d.do_a_thing(1); // calls also_does_a_thing::do_a_thing
}
使用时使用:
struct derived : does_a_thing, also_does_a_thing
{
using does_a_thing::do_a_thing;
using also_does_a_thing::do_a_thing;
};
int main(){
derived d;
d.do_a_thing(1); // calls also_does_a_thing::do_a_thing
}
清洁剂,对吗
变量使用
声明
所以C++11问世了,我们都对这些新特性印象深刻,但是在使用语句时,有一个小差距没有解决;“如果我想为每个基类使用一个,其中这些基类是模板参数,该怎么办?”
比如说:
int a = /*...*/;
double b = /*...*/;
char c = /*...*/;
foo(a, b, c);
template<int, double, char>
void foo(Arguments[3] args){}
template<class T, class U>
struct derived : T, U
{
using T::do_a_thing;
using U::do_a_thing;
};
int main(){
derived<does_a_thing, also_does_a_thing> d;
d.do_a_thing(1); // calls also_does_a_thing::do_a_thing
}
std::vector<int> vec{1, 2, 3};
IteratorWrapper iter_wrapper(vec);
std::list<double> lst{4.1, 5.2};
IteratorWrapper lst_wrapper(lst);
当时,使用
由于缺少变量支持而受到阻碍,因此我们无法(轻松地)做到这一点
然后C++17出现了,并为我们提供了变量使用支持,以便我们能够做到:
现在,如果我作为调用方想要创建IteratorWrapper
的实例,我必须做一些额外的工作来消除T
的歧义,因为它没有包含在构造函数的签名中:
std::vector<int> vec{1, 2, 3};
IteratorWrapper<typename std::vector<int>::const_iterator> iter_wrapper(vec);
template<class... T>
struct templated_ctor{
template<class... U>
overloaded(U...){}
};
很漂亮,对吧
现在我们可以理解第二行代码了
*我知道我在这里做得太过火了,但写下来并真正彻底地回答这个问题很有趣:-)不是…
操作符,而是调用操作符操作符()
,带有可变模板扩展。它本质上意味着使用T1::operator();正在使用T2::运算符()
用于Ts
中的所有T
s。您对哪个部分感到困惑operator()
或…
?运算符后面的三个点容易混淆?可能更明显的等价物是使用a::operator(),B::operator()代码>(现在在C++17中也被允许),更明显地是单个using声明中列表的扩展。@Caleth您是什么意思?正如语法所定义的,“使用Ts::operator()…;
”是一个单一的using声明。“使用A::operator(),B::operator();
”是一个单一的使用声明。“使用A::operator();使用B::operator();
”是两种使用声明的方法。最后两个的含义完全相同。在结构中使用声明是在C++11之前。@Eugene:谢谢!更新历史准确性。