滥用逗号运算符

发布于 2024-08-07 07:21:01 字数 824 浏览 6 评论 0原文

我正在寻找一种在编译时构建字符串数组的简单方法。为了进行测试,我将一个名为 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" 会调用复制构造函数,然后一切都会行为与第一个示例相同。但我收到错误:错误 C2059:语法错误:'string'

但是,这工作正常:

Strings s="Hello"; 

所以我知道复制构造函数至少适用于一个字符串。有什么想法吗?我真的很想让第二种方法起作用,只是为了让代码更干净一些。

I'm looking for an easy way to build an array of strings at compile time. For a test, I put together a class named Strings that has the following members:

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

Using this, I can successfully compile code like this:

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

The s="Hello" part invokes the operator= which returns a Strings& and then the operator, get called for "World!".

What I can't get to work (in MSVC, haven't tried any other compilers yet) is

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

I'd assume here that Strings s="Hello" would call the copy constructor and then everything would behave the same as the first example. But I get the error: error C2059: syntax error : 'string'

However, this works fine:

Strings s="Hello"; 

So I know that the copy constructor does at least work for one string. Any ideas? I'd really like to have the second method work just to make the code a little cleaner.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

这个俗人 2024-08-14 07:21:02

如果你使用c++0x,他们有新的初始化器列表 !我希望你能使用这些。例如:

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

If you c++0x, they have new inializer lists for this! I wish you could use those. For example:

std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };
std::vector<std::string> v{ "xyzzy", "plugh", "abracadabra" };
时常饿 2024-08-14 07:21:01

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

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

int a=3, b=4

在我看来,您本质上是在编写:

Strings s="Hello", stringliteral

因此编译器期望逗号后面的项目是变量的名称,而不是它看到字符串文字并宣布错误。换句话说,构造函数应用于“Hello”,但后面的逗号不是字符串的逗号运算符。

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

I think that the comma in your second example is not the comma operator but rather the grammar element for multiple variable declarations.

e.g., the same way that you can write:

int a=3, b=4

It seems to me that you are essentially writing:

Strings s="Hello", stringliteral

So the compiler expects the item after the comma to be the name of a variable, and instead it sees a string literal and announces an error. In other words, the constructor is applied to "Hello", but the comma afterwards is not the comma operator of Strings.

By the way, the constructor is not really a copy constructor. It creates a Strings object from a literal string parameter... The term copy constructor is typically applied to the same type.

生死何惧 2024-08-14 07:21:01

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

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

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

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

我上面的示例将如下所示:

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

这可能会起作用,但简写语法可能不值得它所带来的棘手语义。

I wouldn't recommend this kind of an API. You are going to continue discovering cases that don't work as expected, since comma is the operator with the lowest precedence. For example, this case won't work either:

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

You may be able to get things working if you use brackets every time around the set of strings, like this:

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

And my example above would look like this:

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

That can likely be made to work, but the shorthand syntax is probably not worth the tricky semantics that come with it.

林空鹿饮溪 2024-08-14 07:21:01

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

#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;
}

It's possible to make this work, for a sufficiently loose definition of "work." Here's a working example I wrote in response to a similar question some years ago. It was fun as a challenge, but I wouldn't use it in real code:

#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;
}
[旋木] 2024-08-14 07:21:01

您可以使用字符指针数组

Strings::Strings(const char* input[]);

const char* input[] = {
  "string one",
  "string two",
  0};

Strings s(input);

,并在构造函数内迭代指针,直到达到 null。

You could use an array of character pointers

Strings::Strings(const char* input[]);

const char* input[] = {
  "string one",
  "string two",
  0};

Strings s(input);

and inside the constructor, iterate through the pointers until you hit the null.

壹場煙雨 2024-08-14 07:21:01

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

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

If the only job of Strings is to store a list of strings, then boost::assign could do the job better with standard containers, I think :)

using namespace boost::assign;
vector<string> listOfThings;
listOfThings += "Hello", "World!";
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文