User 10482
User 10482

Reputation: 1012

Specialized template accepting constructor parameter when only default constructor defined

So, I have this template class and its specialization.

    #include <iostream>

    using namespace std;

    template<bool> struct CompileTimeChecker{

         CompileTimeChecker(...); //constructor, can accept any number of parameters;

    };

    //specialized template definition

    template<> struct CompileTimeChecker<false> {

        //default constructor, body empty

    };

Case 1:

In the main function I am defining a local class called ErrorA. When I create a temporary of CompileTimeChecker<false> with temporary object of ErrorA fed as an initializer, the compiler is not detecting any error.

int main()
{

    class ErrorA {};

    CompileTimeChecker<false>(ErrorA()); //Case 1;

    CompileTimeChecker<false>(int());    //Case 2;

    return 0;

}

Case 2:

Next I feed it with temporary object of type int, and suddenly the compiler recognizes the issue (there is no constructor that takes args in the specialized template CompileTimeChecker<false>)

main.cpp:30:36: error: no matching function for call to ‘CompileTimeChecker::CompileTimeChecker(int)’ CompileTimeChecker<false>(int());

main.cpp:21:23: note: candidate: constexpr CompileTimeChecker::CompileTimeChecker()
     template<> struct CompileTimeChecker<false> {
                       ^~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:21:23: note:   candidate expects 0 arguments, 1 provided

Why does it not recognize the issue in case 1?

Upvotes: 1

Views: 53

Answers (1)

Igor Tandetnik
Igor Tandetnik

Reputation: 52546

CompileTimeChecker<false>(ErrorA());

does not create a temporary of type CompileTimeChecker<false>, passing a temporary ErrorA() to its constructor. Rather, it declares a function named ErrorA, taking no parameters and returning CompileTimeChecker<false> . See also: most vexing parse.

On the other hand, CompileTimeChecker<false>(int()); cannot be parsed as a declaration, so it does unambiguously create a temporary of type CompileTimeChecker<false>.

The easiest way out is to use braces in place of parens to indicate initialization:

CompileTimeChecker<false>{ErrorA{}};

Upvotes: 2

Related Questions