WorldSEnder
WorldSEnder

Reputation: 5054

Interesting behaviour when calling constructor in templated constructor

I just created a really little project I thought I could do in no time (it's about basic delegates) when I came across an interesting compiler bug that I couldn't track down. Here is the simplified version of the code:

class NoComp {
};

class Comp {
    bool operator==(const Comp& other)
    { std::cout << "Working!" << std::endl; return true;}
};

struct Test {
    template<typename T>
    Test(T&& obj) {}
    bool operator==(const Test& other);
};
int main()
{
    Test a(Comp());
    Test b(NoComp());
    a.operator ==(b);
}

This produces the following compiler error when compiled with g++ version 4.8.3 20140911 (Red Hat 4.8.3-7) (GCC) found here:

main.cpp: In function 'int main()':                                    
main.cpp:22:13: error: request for member 'operator==' in 'a', which is
 of non-class type 'Test(Comp (*)())'                                  
  a.operator ==(b);                                                    

I can't figure out what that error means and why it even exists. What happens there, is it a bug or covered by the standard? How can I dodge that, if I can?

Upvotes: 0

Views: 79

Answers (2)

vsoftco
vsoftco

Reputation: 56577

You have what is called the most vexing parse.

The lines

Test a(Comp());
Test b(NoComp());

do not declare variables, but two functions a and b, taking a pointer-to-function that returs Comp (NoComp) and takes no parameters.

If you have access to C++11, use the list-initialization, i.e.

Test a{Comp()};
Test b{NoComp()};

or if you don't, use double parenthesis

Test a((Comp()));
Test b((NoComp()));

Upvotes: 3

Columbo
Columbo

Reputation: 61009

Test a(Comp());
Test b(NoComp());

This declares two functions called a and b. The first one has one parameter of type Comp(*)() and a return type of Test, and the second one takes a NoComp(*)() and also returns a Test. Comp() is a function type and, as all parameters of function type, adjusted to a pointer-to-function type. Same goes for NoComp().

Use double parentheses:

Test a((Comp()));
Test b((NoComp()));

Or list-initialization as of C++11.

Upvotes: 7

Related Questions