Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Omit angle brackets when template has default parameters

Suppose we have a class template with default template parameter:

template <typename T = int>
class Foo {};

We can omit angle brackets when creating a variable inside a function:

int main()
{
    Foo a; // gets properly deduced as Foo<int>
}

But we can't do that for member variables:

struct S
{
    Foo a; // Deduce Foo<int>
};

We can't have derivative types such as this:

Foo* ptr; // Foo<int>*
Foo& ref; // Foo<int>&
int Foo::* mem_ptr; // int Foo<int>::*
std::function<Foo(const Foo&)> fn; // std::function<Foo<int>(const Foo<int>&)>

We can't accept parameters and return them:

Foo Bar(const Foo&); // Foo<int> (*)(const Foo<int>&)

Why? Is this considered a bug in the standard? Is there a proposal to fix it? Are there any actual problems with omitting angle brackets?

My use case:

I have a class template which provides default argument. The template parameter is an expert-only feature that I myself never use but it is there for those 1% of experts who want that total flexibility. Now for other 99% I want to hide the fact that Foo is actually a class template but it doesn't work because users have to type Foo<> when declaring it as a member variable, current solution is this:

template <typename T = int>
class BasicFoo {};

using Foo = BasicFoo<>;

But it complicates implementation code and is not elegant at all.


1 Answers

Is this considered a bug in the standard?

No.

Templates are a named construct which generates another construct (classes/functions/variables) based on a set of parameters. The name of a template is not the name of the construct which it generates. The name of a template is just the name of the template; to name the thing the template generates, you must provide the template parameters.

Foo is the name of a template; Foo<> is the name of a class generated by that template and its associated template parameters.

There are a couple of places where C++ allows a template to be used in such a way that its parameters are deduced from a sequence of expressions. But these are very specific places, created for convenience purposes. They do not exist for the purpose of hiding the fact that a name represents a template rather than the generated construct.

Is there a proposal to fix it?

There is nothing broken to fix. And there are at present no proposals adding changes in this way.

Are there any actual problems with omitting angle brackets?

Define "actual problem". Is it theoretically possible to have the language altered so that, if all of a template's parameters are defaulted, the name of the template can be used without template parameters to simultaneously mean the template and the thing the template generates?

It is probably possible. But it would be complicated to specify. You would need a serious spec-doctor, one who understands the C++ grammar at a deep level, to know for sure whether it is possible, and what exactly would need to be changed to do it.

But at the end of the day, it would only ever be useful for a small, select set of templates: templates that have default values for all of its parameters. The real question is whether that is a common enough case to be worth the effort.

like image 164
Nicol Bolas Avatar answered Aug 07 '26 23:08

Nicol Bolas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!