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?
It’s a function declaration for a function taking a reference to a
boost:function <void()>and returning aSomeClass. 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 section8.2of the C++ Standard.That means, the following will be taken as a parameter declaration, with superfluous parentheses
If you remove the parentheses, this will become clear
And thus, the whole declaration will not anymore declare an object, but a function
To fix it, use the cast-notation
Or put parentheses around the whole expression, like you did.
Here is the Standard in all its glory from
8.2:Note that for controlling precedence, you are allowed to introduce parentheses just about anywhere, like in the following