Search code examples
c++templatestype-deduction

How to force compiler to deduce a class template argument?


I'm new to c++ templates and I'm (quite unsuccessfully) trying to force compiler to deduce template typename argument in initialization.

Here is my code.

template <typename T>
class C
{
public:
        T a;
        C(T a) : a(a) {}
        C(const C<T>& other) : a(other.a) {}
};

int main()
{
        C<int> x(1);
        C y{ x };

        return 0;
}

This code compiled by g++ results in error.

test.cpp:13:11: error: missing template arguments before ‘y’
         C y{ x };
           ^

I would like to maintain this syntax - just C without explicitely specifiing the template argument.

I have tried to use deduction guides, but it only raised another error.

template <typename T> C(const C<T>& other) -> C<T>;

When I inserted this line below the definition of the C class, I got this.

test.cpp:10:51: error: expected constructor, destructor, or type conversion before ‘;’ token
 template <typename T> C(const C<T>& other) -> C<T>;
                                                   ^

Another error occurred when I put this line inside the the C class definition (at the top).

C(const C<T>& other) -> C<T>;
test.cpp:4:26: error: ‘C’ function with trailing return type not declared with ‘auto’ type specifier
  C(const C<T>& other) -> C<T>;
                          ^~~~

In both cases, the first mention error is still present.

Thank you!


Solution

  • In C++11, only template functions could have their template parameters deduced. For example, given:

    void f(std::pair<int, char> &s);
    

    , one could call it with

    f(std::make_pair(5, 'c'));
    

    , since std::make_pair is a function and template arguments can be deduced for functions.

    However, it is illegal to call it with a pair:

    f(std::pair(5, 'c'));
    

    , since there is no template argument deduction for class templates. This issue has been fixed in C++17, making the std::make_pair a bit obsolete.

    More about the new class template argument deduction can be found here.

    To address your issue, I have been able to get the same error when compiling with gcc using C++11. The code compiles without errors with C++17 (for gcc, this can be done by passing the -std=c++17 argument).