Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why don't I need template parameters in this particular case?

I have this code:

struct Base {};

template<typename T>
struct Foo : Base {};

struct Bar {
    template<typename T> //           v--- What's happening here?
    Bar(T foo) : baz{std::make_unique<Foo>(foo)} {}

    std::unique_ptr<Base> baz;
};

As a surprise, GCC and Clang accept and compiles it. It seem to deduce the template parameter of Foo, but it wouldn't make sense. How come the compilers accept that even if there is no overload of std::make_unique that takes a template template parameter? Live example

like image 214
Guillaume Racicot Avatar asked Mar 09 '17 22:03

Guillaume Racicot


People also ask

Can template have default parameters?

You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };

What is a purpose is template parameter?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

Which is a correct example of template parameters?

For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.

What are template parameters?

In UML models, template parameters are formal parameters that once bound to actual values, called template arguments, make templates usable model elements. You can use template parameters to create general definitions of particular types of template.


Video Answer


2 Answers

There are some situations where a template is always invalid, no matter what template arguments are supplied, but the compiler isn't able to figure that out, because it doesn't have the ability to try substituting every possible set of template arguments. According to the standard ([temp.res]/8):

If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required.

That means that the compiler is allowed to be smart and prove that there is no valid specialization, and produce a compilation error, but it's also allowed to not be smart enough, and not produce a compilation error. Of course, once the template is instantiated, then the compiler must diagnose the error.

It's not illegal to use the name of a template without template arguments. There are some circumstances where the compiler can deduce arguments. For example:

template <class T>
void foo(T x);

int main() {
    void (*p)(int) = foo;  // p points to foo<int>
}

In your code, it turns out that you've used Foo in a context where the template arguments can't be deduced. If the compilers were smarter, they would have figured that out. But the fact that they didn't manage to figure it out does not mean your code is correct.

like image 148
Brian Bi Avatar answered Oct 18 '22 14:10

Brian Bi


The reason this works is because C++ doesn't actually create template functions until they're called from somewhere in the code. In this instance, since your code doesn't ever try to create a Bar, your template one-arg Bar constructor is never generated, so the compiler never needs to check if the code is correct.

Template functions are generated by the compiler as soon as they're used, and they're generated only based on the types passed into them. So, if you try to create a Bar like so:

Foo<int> f;
Bar b = Bar(f);

The compiler will try to generate the constructor and fail with an error like:

error C2955: 'Foo' : use of class template requires template argument list

Because it now knows the code is wrong.

If you think about it, this is how it has to work: since C++ doesn't allow you to put constraints on template types, the compiler would have to try every possible combination of template types to figure out if a template function has syntax errors.

like image 32
Daniel Eisener Avatar answered Oct 18 '22 13:10

Daniel Eisener