Home > Blockchain >  Template type deduction in container initialisation
Template type deduction in container initialisation

Time:12-06

I understand that a template type parameter can be defaulted, however, this doesn't work when I attempt to construct a std::vector without supplying the template argument:

#include<vector>

template <typename Int = int>
struct integer{
    Int i;
};

int main(){

    integer num;

    std::vector<integer> vec;

    return 0;
}

This code returns a type value mismatch (compiler explorer link). Is it possible to fix this without writing std::vector<integer<int>>

CodePudding user response:

If you have a function with a default parameter:

 int foo(int bar=0);

To call this function you still have to write:

 int n=foo();

attempting to write int n=foo; will not work, of course. For the same reason if your template's parameters are defaulted you still have to use

  integer<>

to instantiate the template instead of

  integer

CodePudding user response:

You could create an alias integer_t for interger<> using using.

template <typename Int = int>
struct integer{
    Int i;
};
using integer_t = integer<>;

int main(){
   std::vector<integer_t> vec; // No error.
}

The reason why std::vector<integer> did not work is explained in this answer.

CodePudding user response:

You can provide a wrapper that accepts template template parameter (read below):

template <template <typename> class TT, 
         typename T = int>
using my_vector = std::vector<TT<T>>;

my_vector<integer> vec{}; // works
my_vector<integer, long> vecLong{}; // using non-default type

Templates have different types of template parameters:
Each parameter in a parameter-list may be:

a non-type template parameter;
a type template parameter;
a template template parameter.

template <typename>
struct with_type_parameter{};

template <template <typename> class>
struct with_template_template_parameter{};

So, there is an explicit difference for compiler between your integer<> and integer.

  • The first one is a type explicitly instantiated from a template parameter.
  • The second one is a template template.

So, when you instantiate a class template std::vector with a template template integer instead of a type integer<> for an argument, you get the error you have. Because these two things are different for class templates.

However, there is a different behavior fo function templates, since they are allowed for overloading.

Here is an example for you: https://godbolt.org/z/cbnss17aj

template <typename>
struct with_typename{};

// can't have that. class template can only be specialized when declared
// template <template <typename> class>
// struct with_typename{}; 

#include <iostream>

template <typename>
void with_typename_fn()
{
    std::cout << "type" << std::endl;
}

// perfectly fine, since function template overloading is allowed in C  
template <template <typename> class>
void with_typename_fn()
{
    std::cout << "template template" << std::endl;
}

template <typename>
struct non_defaulted{};

template <typename = int>
struct defaulted{};

int main()
{
    with_typename_fn<int>(); // ok
    with_typename_fn<non_defaulted>(); // also ok
    with_typename_fn<defaulted>(); // also ok, but will resolve to template template specialization!
}

Output:

type
template template
template template
  •  Tags:  
  • c
  • Related