【问题标题】:Abusing the comma operator滥用逗号运算符
【发布时间】:2009-10-12 22:16:34
【问题描述】:

我正在寻找一种在编译时构建字符串数组的简单方法。为了进行测试,我整理了一个名为 Strings 的类,该类具有以下成员:

Strings(); 
Strings(const Strings& that);
Strings(const char* s1);
Strings& operator=(const char* s1);
Strings& operator,(const char* s2);

使用它,我可以成功编译如下代码:

Strings s;
s="Hello","World!";

s="Hello" 部分调用operator=,它返回一个Strings&,然后operator, 被调用为"World!"

我无法工作(在 MSVC 中,尚未尝试任何其他编译器)是

Strings s="Hello","World!";

我在这里假设Strings s="Hello" 将调用复制构造函数,然后一切都将与第一个示例相同。但我得到了错误:error C2059: syntax error : 'string'

但是,这很好用:

Strings s="Hello"; 

所以我知道复制构造函数至少对一个字符串有效。有任何想法吗?我真的很想让第二种方法工作,只是为了让代码更简洁。

【问题讨论】:

  • 哇,我听说过很多关于重载逗号运算符的笑话。我从没想过有人会真正做到
  • @Carl:boost.org/doc/libs/1_40_0/libs/assign/doc/index.html#intro 怎么样(非常像 OP 想要的东西)
  • 颤抖 给自己的棺材钉钉子。当它开始出错时,你将如何调试它?
  • @Carl:你是说现在? :)
  • 对于可编写脚本的接口,我强烈建议不要使用 C++。您最好选择像 Lua (lua.org) 这样设计 可编写脚本和嵌入的东西。沿着试图使 C++ 更友好的道路前进会导致深渊和黑暗的地方。

标签: c++ overloading comma-operator


【解决方案1】:

我认为第二个示例中的逗号不是逗号运算符,而是多个变量声明的语法元素。

例如,您可以编写相同的方式:

int a=3, b=4

在我看来,您实际上是在写作:

Strings s="Hello", stringliteral

因此编译器期望逗号后面的项目是变量的名称,而是看到一个字符串文字并宣布错误。也就是说,构造函数作用于“Hello”,但是后面的逗号不是Strings的逗号操作符。

顺便说一句,构造函数并不是真正的复制构造函数。它从文字字符串参数创建一个 Strings 对象...术语复制构造函数通常应用于相同的类型。

【讨论】:

  • Strings s="Hello";Strings s = Strings("Hello"); 等价有可能变得乏味迂腐。它要求复制 ctor 是可调用的,甚至可以调用它,以便从临时对象构造 s。但是使用 sconst char* 构造函数直接初始化替换它的优化,没有任何临时的,是允许和常见的。
  • 呃,不敢相信我没有看到那个。
【解决方案2】:

我不会推荐这种 API。您将继续发现无法按预期工作的情况,因为逗号是优先级最低的运算符。例如,这种情况也不行:

if ("Hello","world" == otherStrings) { ... }

如果您每次都在字符串集周围使用方括号,您可能能够使事情正常进行,如下所示:

Strings s=("Hello","World!");

我上面的例子看起来像这样:

if (("Hello","world") == otherStrings) { ... }

这可能会起作用,但速记语法可能不值得随之而来的棘手语义。

【讨论】:

  • 可以让它工作吗?我预见的问题是你不能为const char*重载operator,,所以("Hello","world")"world"是一样的。
  • 我假设你可以重载运算符,(const char*, const char*)。有没有理由不能这样做?老实说,我不怎么做 C++ 编程。
【解决方案3】:

使用boost::list_of

【讨论】:

    【解决方案4】:

    对于“工作”的足够宽松的定义,有可能使这项工作发挥作用。这是我几年前为回答类似问题而写的一个工作示例。挑战很有趣,但我不会在实际代码中使用它:

    #include <iostream>
    #include <algorithm>
    #include <iterator>
    #include <vector>
    
    void f0(std::vector<int> const &v) { 
        std::copy(v.begin(), v.end(), 
            std::ostream_iterator<int>(std::cout, "\t"));
        std::cout << "\n";
    }
    
    template<class T>
    class make_vector {
        std::vector<T> data;
    public:
        make_vector(T const &val) { 
            data.push_back(val);
        }
    
        make_vector<T> &operator,(T const &t) {
            data.push_back(t);
            return *this;
        }
    
        operator std::vector<T>() { return data; }
    };
    
    template<class T> 
    make_vector<T> makeVect(T const &t) { 
        return make_vector<T>(t);
    }
    
    int main() { 
        f0((makeVect(1), 2, 3, 4, 5));
        f0((makeVect(1), 2, 3));
        return 0;
    }
    

    【讨论】:

      【解决方案5】:

      你可以使用一个字符指针数组

      Strings::Strings(const char* input[]);
      
      const char* input[] = {
        "string one",
        "string two",
        0};
      
      Strings s(input);
      

      在构造函数内部,遍历指针,直到找到空值。

      【讨论】:

      • 或模板构造函数:template &lt;int N&gt; Strings(const char* (&amp;input)[N]) { for (int i = 0; i &lt; N; ++i) push_back(input[i]); }。然后不需要空终止符:你可以做const char *input[] = { "this", "that"}; Strings s(input);。不确定它是否真的值得,但如果你喜欢那种东西,会很有趣。
      • 哦,或者构造函数模板当然可以调用另一个类似于vector::insert(iterator, InputIterator, InputIterator)的函数,以避免在不同位置调用它时生成重复代码。
      【解决方案6】:

      如果Strings 的唯一工作是存储字符串列表,那么boost::assign 可以使用标准容器更好地完成这项工作,我认为:)

      using namespace boost::assign;
      vector<string> listOfThings;
      listOfThings += "Hello", "World!";
      

      【讨论】:

        【解决方案7】:

        如果你是 c++0x,他们有新的inializer lists !我希望你能用这些。例如:

        std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };
        std::vector<std::string> v{ "xyzzy", "plugh", "abracadabra" };
        

        【讨论】:

          猜你喜欢
          • 2010-10-04
          • 2017-07-11
          • 2010-12-16
          • 1970-01-01
          • 2011-03-08
          • 2016-08-22
          • 2016-03-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多