在构造函数参数列表中构造 boost::function 对象时出现错误 C2228

发布于 2024-07-24 12:35:55 字数 722 浏览 6 评论 0原文

下面的代码无法在 Visual C++ 2005 中编译。

class SomeClass {
public: boost::function<void()> func;
        SomeClass(boost::function<void()> &func): func(func) { }
};

void someFunc() {
    std::cout << "someFunc" << std::endl;
}

int main() {
    SomeClass sc(boost::function<void()>(&someFunc));
    sc.func(); // error C2228: left of '.func' must have class/struct/union
    return 0;
}

如果我在 SomeClass 构造函数的参数两边加上括号,或者在参数列表之外构造 boost::function 对象,则它可以正常编译。

    SomeClass sc((boost::function<void()>(&someFunc)));
    // or
    boost::function<void()> f(&someFunc);
    SomeClass sc(f);

前面的代码有什么问题?

The code below does not compile in Visual C++ 2005.

class SomeClass {
public: boost::function<void()> func;
        SomeClass(boost::function<void()> &func): func(func) { }
};

void someFunc() {
    std::cout << "someFunc" << std::endl;
}

int main() {
    SomeClass sc(boost::function<void()>(&someFunc));
    sc.func(); // error C2228: left of '.func' must have class/struct/union
    return 0;
}

If I put parentheses around the argument to the SomeClass constructor or constructs the boost::function object outside the argument list it compiles fine.

    SomeClass sc((boost::function<void()>(&someFunc)));
    // or
    boost::function<void()> f(&someFunc);
    SomeClass sc(f);

What is the problem with the previous code?

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

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

发布评论

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

评论(2

倚栏听风 2024-07-31 12:35:55

它是一个函数的函数声明,该函数引用 boost:function 并返回 SomeClass。 您可以记住以下规则,该规则适用于许多其他此类消歧案例。 您可以在 C++ 标准的 8.2 部分中找到这些情况的描述。

任何可能是声明的构造都将被视为声明

这意味着,以下内容将被视为参数声明,带有多余的括号

boost::function<void()>(&someFunc)

如果删除括号,这将变得清晰

boost::function<void()> &someFunc

因此,整个声明将不再声明一个对象,但一个函数

SomeClass sc(boost::function<void()> &someFunc);

要修复它,请使用强制转换符号

SomeClass sc((boost::function<void()>)&someFunc);

或在整个表达式周围放置括号,就像您所做的那样。

以下是 8.2 中的标准:

由于函数样式转换和 6.8 中提到的声明之间的相似性而产生的歧义也可能出现在声明的上下文中。 在这种情况下,需要在参数名称周围带有一组冗余括号的函数声明和带有函数样式强制转换作为初始值设定项的对象声明之间进行选择。 正如 6.8 中提到的歧义一样,决议将考虑任何可能是声明的构造。 [注意:声明可以通过非函数风格的强制转换、通过 = 来指示初始化或通过删除参数名称周围的多余括号来显式消除歧义。 ]

请注意,为了控制优先级,您可以在任何地方引入括号,如下所示

int (((((((a))))))) = 3;
int (*(pa)) = &a;

It's a function declaration for a function taking a reference to a boost:function <void()> and returning a SomeClass. You can memorize the following rule, which turns out to apply to many other such disambiguation cases. You can find descriptions of these cases in section 8.2 of the C++ Standard.

Any construct that could possibly be a declaration will be taken as a declaration

That means, the following will be taken as a parameter declaration, with superfluous parentheses

boost::function<void()>(&someFunc)

If you remove the parentheses, this will become clear

boost::function<void()> &someFunc

And thus, the whole declaration will not anymore declare an object, but a function

SomeClass sc(boost::function<void()> &someFunc);

To fix it, use the cast-notation

SomeClass sc((boost::function<void()>)&someFunc);

Or put parentheses around the whole expression, like you did.

Here is the Standard in all its glory from 8.2:

The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8 can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any construct that could possibly be a declaration a declaration. [Note: a declaration can be explicitly disambiguated by a nonfunction-style cast, by a = to indicate initialization or by removing the redundant parentheses around the parameter name. ]

Note that for controlling precedence, you are allowed to introduce parentheses just about anywhere, like in the following

int (((((((a))))))) = 3;
int (*(pa)) = &a;
我喜欢麦丽素 2024-07-31 12:35:55

这被称为“C++ 最令人烦恼的解析”(摘自 Scott 所著的一本书迈耶斯称之为有效的 STL)。

正如上面的回答,编译器更喜欢将有问题的行解释为函数声明。

This is known as "C++'s Most Vexing Parse" (from a book by Scott Meyers called Effective STL).

As answered above, the compiler prefers to interpret the problematic line as a function declaration.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文