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