If I am allowed to do the following:
template <typename T = int>
class Foo{
};
Why am I not allowed to do the following in main?
Foo me;
But I must specify the following:
Foo<int> me;
C++11 introduced default template arguments and right now they are being elusive to my complete understanding.
Note:
Foo me;
without template arguments is legal as of C++17. See this answer: https://stackoverflow.com/a/50970942/539997.
Original answer applicable before C++17:
You have to do:
Foo<> me;
The template arguments must be present but you can leave them empty.
Think of it like a function foo
with a single default argument. The expression foo
won't call it, but foo()
will. The argument syntax must still be there. This is consistent with that.
With C++17, you can indeed.
This feature is called class template argument deduction and add more flexibility to the way you can declare variables of templated types.
So,
template <typename T = int>
class Foo{};
int main() {
Foo f;
}
is now legal C++ code.
You are not allowed to do that but you can do this
typedef Foo<> Fooo;
and then do
Fooo me;
typedef Foo<float> Fooo;
, without a default type?
using Fooo = Foo<>;
You can use the following:
Foo<> me;
And have int
be your template argument. The angular brackets are necessary and cannot be omitted.
Somewhat different case and rather later but where a template function is involved. gcc 11.2 can't seem to compile this:
template <typename T = int>
struct Test {};
template<typename T> void foo(T& bar) {}
int main()
{
Test t;
foo<Test>(t);
}
template <typename T = int>
struct Test {};
template<typename T> void foo(T& bar) {}
int main()
{
Test t;
foo<Test<>>(t);
}
Of course
template <typename T = int>
struct Test {};
template<typename T> void foo(T& bar) {}
int main()
{
Test t;
foo(t);
}
works - but sometimes you need to explicitly force the type. Is this a compiler bug?
foo<Test>(t)
), you need to provide <> for every defaulted template - however just putting foo(t)
works fine.
As per the C++17
Standard, template arguments are necessary to be passed.
But if you still want a way around this, you can use using
keyword like this
template <typename T>
class Foo{
};
using IFoo=Foo<int>
Or, you can also use preprocessor
like this
template <typename T>
class Foo{
};
#define IFoo Foo<int>
Quick Reminder
Preprocessors are bad for debugging.
using IFoo=Foo<int>
. Macro's ignore namespaces
Success story sharing
Foo
might be a template identifier or might be an explicit instantiation depending on whether there's a default argument. Better keep the explicit instantiation syntax. Think of it like a functionfoo
with a single default parameter. You can't call it likefoo
, you call it withfoo()
. It makes sense to keep this consistent.foo
either; you can name a class with no arguments asFoo
however.<>
is no more necessary in this case. Check out my answer for more details.