Why are structs not allowed in template definitions? - c++

The following code yields an error error: ‘struct Foo’ is not a valid type for a template constant parameter:
template <struct Foo>
struct Bar {
};
Why is that so?
template <class Foo>
struct Bar {
};
works perfectly fine and even accepts an struct as argument.

This is just an artifact of the syntax rules - the syntax just lets you use the class or typename keywords to indicate a type template parameter. Otherwise the parameter has to be a 'non-type' template parameter (basically an integral, pointer or reference type).
I suppose Stroustrup (and whoever else he might have taken input from) decided that there was no need to include struct as a a keyword to indicate a type template parameter since there was no need for backwards compatibility with C.
In fact, my recollection (I'll have to do some book readin' when I get back home) is that when typename was added to indicate a template type parameter, Stroustrup would have liked to take away using the class keyword for that purpose (since it was confusing), but there was too much code that relied on it.
Edit:
Turns out the story is more like (from a blog entry by Stan Lippman):
The reason for the two keywords is
historical. In the original template
specification, Stroustrup reused the
existing class keyword to specify a
type parameter rather than introduce a
new keyword that might of course break
existing programs. It wasn't that a
new keyword wasn't considered -- just
that it wasn't considered necessary
given its potential disruption. And up
until the ISO-C++ standard, this was
the only way to declare a type
parameter.
Reuses of existing keywords seems to
always sow confusion. What we found is
that beginners were [wondering]
whether the use of the class
constrained or limited the type
arguments a user could specify to be
class types rather than, say, a
built-in or pointer type. So, there
was some feeling that not having
introduced a new keyword was a
mistake.
During standardization, certain
constructs were discovered within a
template definition that resolved to
expressions although they were meant
to indicate declarations
...
The committee decided that a new
keyword was just the ticket to get the
compiler off its unfortunate obsession
with expressions. The new keyword was
the self-describing typename.
...
Since the keyword was on the payroll,
heck, why not fix the confusion caused
by the original decision to reuse the
class keyword. Of course, given the
extensive body of existing code and
books and articles and talks and
postings using the class keyword, they
chose to also retain support for that
use of the keyword as well. So that's
why you have both.

You can instantiate a template using a struct; however, the syntax for declaring a template type only allows the keywords "class" or "typename" to appear where you are attempting to use the keyword "struct".
I should add that you can also use a specific type (e.g. int), if you want to instantiate your template based on a compile-time constant or based on an object with external linkage... but that's somewhat of an aside.

The short answer is: template <class Foo> even accepts a union or a double - still, neither is allowed instead of class. However, typename is. That's just the way the syntax was defined.
A somewhat longer answer: When templates for C++ where "invented", there was a keyword needed at that place saying that the next identifier would be a type name. It was decided to re-use the existing class keyword. That was a bit confusing, but there's a general reluctance to introducing more keywords, because they always break some existing code which used this as an identifier when it wasn't a keyword.
Later, typename became a keyword for other reasons, and since it is a much better fit, it can now be used in that place: template <typename Foo>. However, with billions of lines of code out there using class in that place, it must remain valid for that purpose. So now both are allowed.
As is common in C++, this created several camps as to what keyword to use in that place. Some stick with class, because they've been using it for more than a decade. Others prefer typename, because it's a much better fit. Some use class when Foo is expected to be of a class type (members are accessed) and typename when built-ins can be used, too.

Because the keyword for template parameters is class or typename. This doesn't restrict the Foo parameter to be a class - it can be of any type.

Related

Template class forward declaration with default argument [duplicate]

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.
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.
I don't consider myself a language expert, but my stance would be that the problem your proposal tries to tackle is solved much simpler in the same way std::(basic_)string does it.
We have
template<
class CharT,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>
> class basic_string;
and then a set of typedefs for "non-expert" users, such as std::string for std::basic_string<char>.
If an expert user wants to make use of the other template parameters, they can themselves define a type alias, which is nice and coherent with the above. Moreover, this cleanly separates the template from the types that are created from it.
Your suggestion of allowing templates with defaults for all parameters to be named by MyTemplate alone, instead of requiring MyTemplate<>, or making use of using MyTemplate = MyBasicTemplate<>;, has the following issues:
It complicates the grammar and specification of the language. You need to touch the allowed syntax of all the contexts mentioned in your question, adding the ability to use a template name where a type name would be expected, but only if the relevant template has default values for all template parameters. And if you don't change all of them, you introduce weirdly inconsistent behavior.
There is some overlap between your suggestion and CTAD, but CTAD is decidedly about reducing type verbosity for initialization. CTAD offers significant comfort within its scope and is extensible through deduction guides, whereas your proposal's syntactic sugar is only relevant in a tiny usage niche, with much smaller benefits.
There is the danger of accidentally using the wrong template parameters (did you mean the default template parameters or did you just forget to specify the ones you wanted?). Even if that is not a concern in your use case, the standard would have to concern itself with that potential issue.
There is also the danger of your suggestion conflicting with deduction guides. Who should win?
Your problem is easily and conveniently solved with existing language tools (see above). I disagree that this "complicates" implementation code (complexity is literally only increased by a single typedef/using, (re)naming your template is absolutely trivial work) or that it is inelegant.
Overall, the problem you intend to solve (saving library implementers a using, or users a <> (or using), exclusively for all-defaulted templates) is fringe at best and will not be a sufficient motivation for significantly altering several core aspects the language. That's my prediction at least.

std::optional with optional variadic template [duplicate]

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.
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.
I don't consider myself a language expert, but my stance would be that the problem your proposal tries to tackle is solved much simpler in the same way std::(basic_)string does it.
We have
template<
class CharT,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>
> class basic_string;
and then a set of typedefs for "non-expert" users, such as std::string for std::basic_string<char>.
If an expert user wants to make use of the other template parameters, they can themselves define a type alias, which is nice and coherent with the above. Moreover, this cleanly separates the template from the types that are created from it.
Your suggestion of allowing templates with defaults for all parameters to be named by MyTemplate alone, instead of requiring MyTemplate<>, or making use of using MyTemplate = MyBasicTemplate<>;, has the following issues:
It complicates the grammar and specification of the language. You need to touch the allowed syntax of all the contexts mentioned in your question, adding the ability to use a template name where a type name would be expected, but only if the relevant template has default values for all template parameters. And if you don't change all of them, you introduce weirdly inconsistent behavior.
There is some overlap between your suggestion and CTAD, but CTAD is decidedly about reducing type verbosity for initialization. CTAD offers significant comfort within its scope and is extensible through deduction guides, whereas your proposal's syntactic sugar is only relevant in a tiny usage niche, with much smaller benefits.
There is the danger of accidentally using the wrong template parameters (did you mean the default template parameters or did you just forget to specify the ones you wanted?). Even if that is not a concern in your use case, the standard would have to concern itself with that potential issue.
There is also the danger of your suggestion conflicting with deduction guides. Who should win?
Your problem is easily and conveniently solved with existing language tools (see above). I disagree that this "complicates" implementation code (complexity is literally only increased by a single typedef/using, (re)naming your template is absolutely trivial work) or that it is inelegant.
Overall, the problem you intend to solve (saving library implementers a using, or users a <> (or using), exclusively for all-defaulted templates) is fringe at best and will not be a sufficient motivation for significantly altering several core aspects the language. That's my prediction at least.

c++ auto for type and nontype templates

In c++17 template <auto> allows to declare templates with arbitrary type parameters. Partially inspired by this question, it would be useful to have an extension of template <auto> that captures both type and nontype template parameters, and also allows for a variadic version of it.
Are there plans for such an extension in the next c++20 release? Is there some fundamental problem in having a syntax like template<auto... X>, with X any type or nontype template parameter?
Are there plans for such an extension in the next c++20 release?
No.
Is there some fundamental problem in having a syntax like template<auto... X>, with X any type or nontype template parameter?
It would be a totally new concept in the language - having a name refer to either a type or a value in the same place. So it'd come with all sorts of additional questions - and probably additional language features to check if X is a type or not.
The syntax likely cannot be template <auto... X> struct Y { }; since that syntax already has meaning and means a bunch of values and Y<int>{} is ill-formed.
There are definitely places where such a thing would be useful though. A proposal would just have to address these issues.
The big issue with trying to do something like that is grammar. Template parameters state up-front whether they are templates, types, or values, and the most important reason for this is grammatical.
C++ is a context-sensitive grammar. That means that you cannot know, just from a sequence of tokens, what a particular sequence of tokens means. For example, IDENTIFIER LEFT_PAREN RIGHT_PAREN SEMICOLON. What does that mean?
It could mean to call a function named by IDENTIFIER with no parameters. It could mean to default initialize a prvalue of a class named by IDENTIFIER. These are rather different things; you might conceptually see them as similar, but C++'s grammar does not.
Templates are not macros; they're not doing token pasting. There is some understanding that a piece of code in a template is supposed to mean a specific thing. And you can only do that if you at least know what kind of thing a template parameter is.
In order to retain this ability, these "omni template parameters" cannot be utilized until you actually know what they mean. So in order to create such a feature in C++, you would need to:
Create a new syntax to declare omni template parameters (auto isn't going to fly, as it already has a specific meaning).
Provide a syntax for determining what kind of thing an omni template parameter is.
Require the user to invoke that syntax before they can use such parameter names in most ways. This would typically be via some form of specialized if constexpr block, but pattern matching proposals represent an interesting alternative/additional way to handle them (since they can be expressions as well as statements). And expansion statements represent a possible way to access all of the omni parameters in a parameter pack.
I can't see how it would be useful that a template argument could be dynamically either a type or a value? The code statements that use types are very different to those that which use constant values introduced through the template argument.
The only way would be a big "if constexpr" which would make it pointless in my view.
Ok, having looked more closely at the referenced question, I guess there is room there for generically pass-through wrapping the various explicit base template implementations that use different parameter orderings. I still fail to see a huge benefit. The compiler errors when it goes wrong are going to be unfathomable, if nothing else!
I remember being told that overloading and templates were going to rid the world of the unfathomable error messages generated from macros. I have yet to see it!

Why C++17 have two keywords(class and typename) for the same purpose in templates

Template template parameter declaration can only use the keyword class
and not typename until C++17.
This is the difference between those until C++17.Since C++17, both are same .
Then why not C++17 deprecating one of the keyword(class) in the template parameter and type parameter declaration?
Because class have two different meaning
This is a subjective question. Personally I would tend to agree that having class here at all is poor form, and typename should have been the only keyword allowed.
But that's just my opinion. Perhaps this usage of class will be deprecated in the future; perhaps there are sufficient people who like to write class for whatever reason, that it won't be.
At the end of the day, it's hardly the most pressing issue to affect C++, which is probably the real reason that the committee ended up relaxing restrictions rather than adding new ones.
If you feel strongly that this usage of class should be deprecated, feel free to propose this to the working group!
By the way, the usage of static you refer to was actually undeprecated in C++11.

Has the C++ standard committee considered templated namespaces?

Namespaces are in many was like classes with no constructors, no destructors, no inheritance, final, and only static methods and members. After all, this kind of classes can essentially be used only the way namespaces are used: a named scope for declarations and definitions.
... except that the above is not true, since classes can be templated - and namespaces cannot. There have been a couple of questions here on the site similar to "can I template a namespace", but what I'd like to know is - has the C++ standard committee ever considered a proposal to make namespaces templatable? If it has, was the proposal rejected? If it was, what were the reasons?
The inability to have a template namespace is actually just one way in which they differ from classes. Others would be things like new namespace, and sizeof (namespace) - how could a compiler implement that, given that a namespace may extend over many compilation units?
Looking just at template namespaces... While it can at times be hard to keep up with all the proposals for new C++ features, I don't recall ever seeing one that attempted to add a feature such as you describe.
Would it ever be considered, assuming someone were to write a proposal? As Stroustrup indicates in this interview (http://www.stroustrup.com/devXinterview.html):
For C++ to remain viable for decades to come, it is essential that
Standard C++ isn't extended to support every academic and commercial
fad. Most language facilities that people ask for can be adequately
addressed through libraries using only current C++ facilities.
As you indicate yourself, what you are asking for is basically already there: just use a templated class with static members. This seems to disqualify it as a potential new feature, at least in the eyes of Stroustrup.
How would ADL work if namespaces can be templated? Are we supposed to create special template deduction rules for ADL then?
More importantly, can you justify the added complexity to the language by demonstrating a use-case that can't be filled by, just make a template struct with only static members? If a template namespace is just like a gimped template struct, that doesn't seem to be very compelling.
Also. I understand you weren't satisfied with the other questions about namespace / template hybrids, but one point in this answer seems to be relevant to your question:
Why can't namespaces be template parameters?
Possibly difficult: A namespace isn't a complete, self-contained entity. Different members of a namespace can be declared in different headers and even different compilation units.
If a namespace is a template, how will this even work? Can you still "reopen" the namespace like you can with a regular namespace? If that's allowed, then what is the point of instantiation of the namespace?
It sounds like it could potentially be extremely complicated.
Also: Will the language still be easily parsable after your proposed feature?
One of the most vexing things in C++ is the need to write template often when defining templates that refer to other templates, in order to resolve ambiguity in the grammar regarding whether < is a less than operator or a template parameter list.
3.4.5 [basic.lookup.classref]
In a class member access expression (5.2.5), if the . or -> token is immediately followed by an identifier followed by a <, the identifier must be looked up to determine whether the < is the beginning of a template argument list (14.2) or a less-than operator. The identifier is first looked up in the class of the object expression. If the identifier is not found, it is then looked up in the context of the entire postfix-expression and shall name a class template. If the lookup in the class of the object expression finds a template, the name is also looked up in the context of the entire postfix-expression and
— if the name is not found, the name found in the class of the object expression is used, otherwise
— if the name is found in the context of the entire postfix-expression and does not name a class template, the name found in the class of the object expression is used, otherwise
— if the name found is a class template, it shall refer to the same entity as the one found in the class of the object expression, otherwise the program is ill-formed.
If namespaces can be templates, don't we have to write template for them also, whenever you will refer to a template after a :: operator? For the same reason that foo::bar < 1 ... could be a namespace template bar inside of template foo with a non-type template parameter, or it could be a comparison of 1 with int foo::bar.
How do we disambiguate between that and the third possibility, foo is a namespace and bar is a regular class template inside of it`?