【问题标题】:C++ overloading operator comma for variadic arguments可变参数的 C++ 重载运算符逗号
【发布时间】:2011-01-24 15:52:19
【问题描述】:

是否可以通过重载参数的运算符逗号来构造函数的可变参数?我想看一个例子如何做到这一点..,也许是这样的:

template <typename T> class ArgList {
public:
    ArgList(const T& a);
    ArgList<T>& operator,(const T& a,const T& b);
}
//declaration
void myFunction(ArgList<int> list);

//in use:
myFunction(1,2,3,4);

//or maybe:
myFunction(ArgList<int>(1),2,3,4);

【问题讨论】:

  • 为什么需要使用逗号操作符?例如。 Boost.Assign 已经为您提供了简洁的语法,但它使用了operator()
  • 因为我希望使用简单如 MyFunction(1,2,3) 而不是 MyFunction(boost::list_of(1)(2)(3))

标签: c++ operators arguments variadic comma-operator


【解决方案1】:

这是有可能的,但用法看起来不太好。例如:

#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>

template <class T>
class list_of
{
    std::vector<T> data;
public:
    typedef typename std::vector<T>::const_iterator const_iterator;
    const_iterator begin() const { return data.begin(); }
    const_iterator end() const { return data.end(); }

    list_of& operator, (const T& t) {
        data.push_back(t);
        return *this;
    }
};

void print(const list_of<int>& args)
{
    std::copy(args.begin(), args.end(), std::ostream_iterator<int>(std::cout, " "));
}

int main()
{
    print( (list_of<int>(), 1, 2, 3, 4, 5) );
}

这个缺点将在 C++0x 中得到修复,你可以这样做:

void print(const std::initializer_list<int>& args)
{
    std::copy(args.begin(), args.end(), std::ostream_iterator<int>(std::cout, " "));
}

int main()
{
    print( {1, 2, 3, 4, 5} );
}

甚至是混合类型:

template <class T>
void print(const T& t)
{
    std::cout << t;
}

template <class Arg1, class ...ArgN>
void print(const Arg1& a1, const ArgN& ...an)
{
    std::cout << a1 << ' ';
    print(an...);
}


int main()
{
    print( 1, 2.4, 'u', "hello world" );
}

【讨论】:

  • initializer_list?我不确定,因为它需要语言的内置支持才能工作。但是这两个 sn-ps 都已经使用 GCC 4.4.1 编译了 std=C++0x
  • 我们可以使用全局静态重载运算符逗号,例如:template&lt;typename T&gt; T&amp; operator, (const T&amp; a, T&amp; b); 吗?
  • 正如 Neil 已经提到的,不适用于 "built-in" 类型,因此您必须以 list_of() 之类的形式开始表达式。
  • 另一件不需要额外括号的事情是使用其他运算符:print(list_of&lt;int&gt;() % 1 % 2 % 3); 如果第一项被赋予返回@987654327 的函数,您也可以使用模板类型推导@:print(make_list_of(1) % 2 % 3); 但它在各方面都很丑。如果可以很好地模拟它,C++0x 不会将更改添加到语言中。
【解决方案2】:

可能是这样的:

class MyArgList {
public:   
     typedef std::list<boost::any> ManyList;

     template <typename T>
     MyArgList& operator, (const T& val) {
        elems.push_back(val);
        return *this; 
     }

     ManyList::iterator begin() {return elems.begin();}
       ...

private:
     ManyList elems;
};

用法如下:

void foo(MyArgList& list);
foo((myArgList(),1,2,3,4,5));

【讨论】:

    【解决方案3】:

    不,不是。由逗号运算符分隔的值列表将被评估为单个值。例如:

    1,2,3
    

    将产生一个值,3。

    【讨论】:

    • 这就是我想要的,该函数仍然接收单个值,但是该值是由运算符逗号构造的,我认为可以执行 MyObject object = (1,2,3),我想可以将其修改为使用 MyObject 作为函数参数
    • @uray 抱歉,这完全不清楚。请修改您的问题以说明您想要做什么。例如,您的示例代码中的 a、b、c 和 d 的类型是什么?请记住,您不能为“内置”类型重载运算符。
    • @uray,问题是你必须在你的参数列表周围加上括号,否则编译器会抱怨函数的参数数量过多,也就是说它不会理解那些是 不是多个参数。
    【解决方案4】:

    运算符具有固定数量的参数。你无法改变这一点。逗号运算符有两个参数。所以不行。不过,您可以通过一些努力推出自定义的级联版本。

    【讨论】:

    • 逗号运算符接受一个参数。
    • @StilesCrisis 逗号操作符实际上可以接受一两个参数。使用两个参数,您可以指定逗号可以出现在操作数之前和另一种类型之后。它甚至比常规的单参数逗号重载更不常见,后者已经非常罕见,但它确实存在。
    猜你喜欢
    • 2022-01-19
    • 2016-08-22
    • 2011-08-01
    • 2020-04-22
    • 2012-05-04
    • 2018-02-20
    • 2017-07-11
    • 2010-12-16
    • 1970-01-01
    相关资源
    最近更新 更多