Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+代码中,`operator()…`是什么意思+;?_C++_Templates_Operator Keyword_C++17_Variant - Fatal编程技术网

C++ 在C+代码中,`operator()…`是什么意思+;?

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

我试图理解std::visit的示例,在这里我看到了以下代码行:

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:谢谢!更新历史准确性。