Can Deduction Guide have an explicit(bool) specifier? - c++

Multiple parts of the standard indicate that deduction guide cannot have an explicit-specifier but can only have an explicit keyword preceding it.
like:
in temp.deduct.duide
deduction-guide:
explicitopt template-name ( parameter-declaration-clause ) -> simple-template-id ;
note that the standard says : explicitopt and not explicit-specifier.
or in dcl.fct.spec
An explicit-specifier shall be used only in the declaration of a constructor or conversion function within its class definition; ...
but the standard also says in over.match.class.deduct
If the function or function template was generated from a constructor or deduction-guide that had an explicit-specifier, each such notional constructor is considered to have that same explicit-specifier.
this quote implies that deduction-guides can have an explicit-specifier.
I do not see any particular reason why deduction guide couldn't have a explicit-specifier.
Is the issue in my understanding of the standard or in the standard itself ?
Can Deduction Guide have an explicit(bool) specifier ?

I do not see any particular reason why deduction guide couldn't have a explicit-specifier.
Me neither. Seems like a total oversight on my part (I'm one of the authors of conditional explicit). I'll try to file a core issue.
Update: This was fixed in P1968, adopted in Belfast, as part of the resolution for core issue 2422.

Related

The "(optional)" marker in cppreference.com documentation

Last week, I had a discussion with a colleague in understanding the documentation of C++ features on cppreference.com. We had a look at the documentation of the parameter packs, in particular the meaning of the (optional) marker:
(Another example can be found here.)
I thought it means that this part of the syntax is optional. Meaning I can omit this part in the syntax, but it is always required to be supported by the compiler to comply with the C++ standard. But he stated that it means that it is optional in the standard and that a compiler does not need to support this feature to comply to the standard. Which is it? Both of these explanations make sense to me.
I couldn't find any kind of explanation on the cppreference web site. I also tried to google it but always landed at std::optional...
The opt / (optional) suffix means the symbol is optional [for the C++ programmer to use; not the compiler to support]
As this question has been tagged language-lawyer, and as general when we look for a definite reference, let's move away from CppReference and into the standard.
Where CppReference uses the (optional) subscript, the standard uses opt; e.g. as in [temp.param]/1:
The syntax for template-parameters is:
template-parameter:
type-parameter
parameter-declaration
type-parameter:
type-parameter-key ...opt identifieropt
[... and so on]
[syntax]/1 describe the syntax notation [emphasis mine]:
In the syntax notation used in this document, syntactic categories are
indicated by italic type, and literal words and characters in constant
width type. Alternatives are listed on separate lines except in a few
cases where a long set of alternatives is marked by the phrase “one
of”. If the text of an alternative is too long to fit on a line, the
text is continued on subsequent lines indented from the first one.
An optional terminal or non-terminal symbol is indicated by the subscript “opt", so
{ expressionopt }
indicates an optional expression enclosed in braces.
Thus, you are correct, and your colleague is wrong. Particularly for your example of template parameter packs (which we introduce by the optional ... after typename) the identifier that follows after typename..., which names the pack (or the template parameter, if ... is omitted), is optional.
But he stated that it means that it is optional in the standard and that a compiler does not need to support this feature to comply to the standard.
The ridiculousness of this claim becomes even more clear if we annotate the "optional permutations" of a class template with a single type template parameter:
template<typename>
// ^^^^^^^^ type-parameter
// (omitting optional '...' and 'identifier')
struct S;
template<typename T>
// ^^^^^^^^^^ type-parameter
// (omitting optional '...')
struct S;
template<typename...>
// ^^^^^^^^^^^ type-parameter
// (omitting optional 'identifier')
struct S;
template<typename... Ts>
// ^^^^^^^^^^^^^^ type-parameter
struct S;
If the claim above was true, only the first of these four would need to be supported by a compliant implementation (based solely on grammar, in this contrived example), which would mean a compiler vendor could offer a compliant implementation where we could never name neither template (type) parameters nor function parameters.
It means that particular token is optional. For instance both these declarations work:
template <class... Args>
void foo();
template <class...>
void bar();
While I found a page that lists all of the marks, I was unable to find a page that specifies what the marks are intended to mean. Still, I might ask your colleague to take a look at some other pages, with the goal of the colleague abandoning the idea that "optional" means "optional to support". (This is not a definitive argument, but many would find it persuasive.) I found two good examples at Function declaration.
Function declaration:
noptr-declarator ( parameter-list ) cv(optional) ref(optional) except(optional) attr(optional)
Focus on cv (short for "const-volatile"), which is marked "optional" and which is "only allowed in non-static member function declarations". Your colleague's interpretation of this marker would mean that compilers do not have to support const member functions, as the const keyword is "optional".
Function definition, the first option for function-body:
ctor-initializer(optional) compound-statement
The "optional" part here is the member initializer list (only allowed in constructors). Is your colleague ready to claim that a compiler need not support member initializer lists?
Sometimes one should look at the familiar to understand annotations.

template with lambda as unique default parameter on each instantiation

I'm looking for a way to automatically make default template parameter be unique each time a template is instantiated. Since unnamed function objects created by lambda expressions have different types I thought of adopting them somehow. With recent changes to standard daft removing "A lambda-expression shall not appear in ... a template-argument" restriction (see Wording for lambdas in unevaluated contexts) it seemed like a good idea. So I wrote the following kinda working snippet that compiles on recent gcc and clang:
#include <type_traits>
template<void ( * ) (void) = [](){}> class
unique final {};
static_assert(false == ::std::is_same_v<unique<>, unique<>>);
int main()
{
return 0;
}
Is this a viable approach or one of those "ill-formed, no diagnostic is required" cases?
Some additional context: I want to use this to implement Ada-style strong type definitions that should work in a single translation unit without manually inventing unique tags that would be otherwise unused:
struct _tag_WowInt {};
using Int = type<int, _tag_WowInt>;
struct _tag_SoUnique {};
using DifferentInt = type<int, _tag_SoUnique>;
Upd1: I would like to mention that approaches involving __COUNTER__ or similar macros won't work in general case because they will be expanded by preprocessor only once and won't yield unique types when used inside of template for example.
I believe that you are right, it seems to me that is "ill-formed, no diagnostic required". I think this is covered by
[temp.res/8.4] and [temp.res/8.5]:
(8.4) ― a hypothetical instantiation of a template immediately following its definition would be ill-formed due to
a construct that does not depend on a template parameter, or
(8.5) ― the interpretation of such a construct in the hypothetical instantiation is different from the interpretation
of the corresponding construct in any actual instantiation of the template. [Note: This can happen in situations including the following:
(8.5.1) ― a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is performed, or
(8.5.2) ― lookup for a name in the template definition found a using-declaration, but the lookup in the corresponding scope in the instantiation does not find any declarations because the using-declaration was a pack expansion and the corresponding pack is empty, or
(8.5.3) ― an instantiation uses a default argument or default template argument that had not been defined at the point at which the template was defined, or
(8.5.4) ― constant expression evaluation within the template instantiation uses
(8.5.4.1) ― the value of a const object of integral or unscoped enumeration type or
(8.5.4.2) ― the value of a constexpr object or
(8.5.4.3) ― the value of a reference or
(8.5.4.4) ― the definition of a constexpr function,
and that entity was not defined when the template was defined, or
(8.5.5) ― a class template specialization or variable template specialization that is specified by a non-dependent simple-template-id is used by the template, and either it is instantiated from a partial specialization that was not defined when the template was defined or it names an explicit specialization that was not declared when the template was defined.
— end note]
Even though your use case is not explicitly listed in the examples of the note, in my understanding the requirement implies that unique<> must refer to the same thing throughout the whole program, otherwise it is ill-formed, no diagnostic required.
This was CWG1850. The Committee appear to dislike this
kind of stateful meta-programming. The constexpr counter no longer works
in newer versions of the compilers.

What does `class template Example<int>;` statement mean with C++11?

I've been referred to "Explicit Template Instantiation" at cplusplus.com, which gives the following example:
template <typename T> class Example
{
public:
Example( T test )
{
_data = test;
}
void setTest(T test)
{
_data = T;
}
private:
T _data;
};
class template Example<int>;
class template Example<float>;
class template Example<double>;
Apart from what looks like an omission error to me where a type is attempted to be assigned to a member variable -- _data = T instead of what I assume should be _data = test -- what I don't understand is what do the last 3 lines declare or instruct the compiler to do, exactly?
I know what templates are, have built programs with them, and know in general about their instantiation and specialization. I do probably have some holes in the understanding of the latter two, but I typically instruct an explicit template instantiation using e.g. template class Example<int>; form and not the one shown in the snippet.
I've tried to compile the snippet using g++ -std=c++11 -pedantic and it compiles just fine and without warnings (I corrected the _date = T error above first).
This came after I commented on an answer to a related question and I am still unsure whether either of the last 3 lines in the snippet is a template specialization or instantiation.
I have also tried to locate the relevant grammar production rule (one allowing template after class) in the C++11 draft published by ISO but came empty handed.
We can see from the following godbolt example this is ill-formed according to clang and MSVC and looking at the draft standard section on Explicit instantiation section [temp.explicit] I don't see any justification for gcc to accepts it.
I believe what the article "possibly" meant given the topic was:
template class Example<int>;
template class Example<float>;
template class Example<double>;
and that indeed is well-formed with gcc/clang/MSVC.
It looks like pre C++11 this grammar was allowed, see defect report 1707: template in elaborated-type-specifier without nested-name-specifier (emphasis mine):
The grammar for elaborated-type-specifier in 10.1.7.3 [dcl.type.elab]
reads, in part,
elaborated-type-specifier:
class-key nested-name-specifieropt templateopt simple-template-id
This allows use of the template keyword without a
nested-name-specifier, e.g., struct template S. This is
inconsistent with other uses of the template keyword. It might be
better to split the production in two and only allow the keyword
following a nested-name-specifier,
....
So this makes a little more sense with this comment that -ansi causes a warning.
The other answerer filed two bug reports.
cppreference has a good dicssuion of Explicit instantiation and this SO question Explicit instantiation - when is it used? explains more details why this is useful.
Also note, we can see this Meta post: Links being changed to cppreference.com that the site has been known to have incorrect information and in general the community prefers cppreference as a solid C++ reference.
I see two bugs here:
GCC treats the template keyword here as the template disambiguator, and thus believes that class template Example<int> is equivalent to class Example<int>. This is incorrect because the C++ grammar only permits the template disambiguator to be after ::, . or ->. (C++11 as originally written allows class template Example<int>, but this has been fixed by cwg 1707.)
GCC incorrectly allows a declaration like class Example<int>;. Although class Example<int>; matches the grammar of simple-declaration, it fails to meet the requirement in [dcl.dcl]/5 which states that a simple-declaration must declare or redeclare something (class/enumeration/enumerator/typedef/variable/function).
The former has been reported as GCC bug 87781, the latter as GCC bug 87783.
Update: GCC bug 87781 is now fixed by r266285.

Is there any guarantee on the order of substitution in a function template after type deduction?

Consider this function template:
template<typename T>
typename soft_error<T>::type foo(T, typename hard_error<T>::type)
{ }
After deducing type T from the type of the first argument in the call to foo(), the compiler will proceed to substitute T and instantiate the function signature.
If substitution for the return type gets executed first, causing a simple substitution failure, the compiler will discard this function template when computing the overload set and search for other viable overloads (SFINAE).
On the other hand, if substitution for the second function parameter occurs first, causing a hard error (e.g. because of a substitution failure in a non-immediate context), the entire compilation would fail.
QUESTION: Is there any guarantee on the order in which substitution will be performed for the function parameters and return types?
NOTE: This example seems to show that on all major compilers (VC11 was tested separately and gave identical results) substitution for the return type occurs before substitution for the parameter types.
[NOTE: This was not originally meant to be a self-answered question, but I happened to find out the solution while crafting the question]
Is there any guarantee on the order in which substitution will be performed for the function parameters and return types?
Not in the current standard.
However, this Defect Report (courtesy of Xeo) shows that this is indeed intended to be the case. Here is the proposed new wording for Paragraph 14.8.2/7 of the C++11 Standard (which has become part of the n3485 draft):
The substitution occurs in all types and expressions that are used in the function type and in template
parameter declarations. The expressions include not only constant expressions such as those that appear in
array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions)
inside sizeof, decltype, and other contexts that allow non-constant expressions. The substitution proceeds
in lexical order and stops when a condition that causes deduction to fail is encountered. [...]
As correctly pointed out by Nicol Bolas in the comments to the question, lexical order means that a trailing return type would be substituted after the parameter types, as shown in this live example.

Static Constant Class Members

Consider the following snippet:
struct Foo
{
static const T value = 123; //Where T is some POD-type
};
const T Foo::value; //Is this required?
In this case, does the standard require us to explicitly declare value in a translation unit? It seems I have conflicting information; boost and things like numeric_limits from the STL seem to do this sort of thing just like in my snippet.
OTOH, I remember reading somewhere (albeit a long long time ago) that you're still required to provide a declaration in a translation unit.
If this is the case, what about template specialization? Will each specialization require a declaration?
I'd appreciate your comments as to what the "right way" is.
You have to provide a definition in a translation unit too, in case you use the value variable. That means, if for example you read its value.
The important thing is that the compiler is not required to give a warning or error if you violate that rule. The Standard says "no diagnostic required" for a violation.
In the next C++ Standard version, the rule changed. A variable is not used when it is used as a constant expression. Simply reading value above where the variable is initialized directly in the class means that still no definition is required then.
See the definition of use in section 3.2 One Definition Rule of the Standard and requirement for a definition for static data-members in 9.4.2, paragraph 4 and 5 (in the C++98 Standard. Appears in paragraph 3 and 4 in the n2800 draft of the next Standard).
Correction: The rule already changed for c++03: If the variable appears where a integral constant expression is required, no definition is needed (quoting from an unofficial revisions list for the 2003 update), see resolution for this language defect report:
An expression is potentially evaluated unless it appears where an integral constant expression is required (see 5.19), is the operand of the sizeof operator (5.3.3), or is the operand of the typeid operator and the expression does not designate an lvalue of polymorphic class type (5.2.8)...
Note that even then, many uses are in cases where an integral constant is not required. Cases where one is, is in array dimensions or in template metaprogramming. So strictly speaking (see this report), only the c++1x solution provides really guarantee that in obvious cases also like "s == string::npos" where an integral constant is not required the definition of the static member is not needed, because the next Standard has a different, better wording of 3.2. This is however quite theoretical stuff, since most (all?) compiler don't moan anyway. Thanks for the guy in the comment section for telling me.
To add on to what litb said, from my copy of n2798:
9.4.2
[...]
2 The declaration of a static data member in its class definition is not a definition and
may be of an incomplete type other than cv-qualified void. The definition for a static
data member shall appear in a namespace scope enclosing the member’s class definition. In
the definition at namespace scope, the name of the static data member shall be qualified
by its class name using the :: operator.
You don't have to provide a definition for static integral constant members if you don't use them in some way that requires them to be stored in memory somewhere (e.g. take the address of such a member). See Stroustrup's The C++ Programming Language, section 10.4.6.2.
Edit:
Oops, I just re-read the question, and the question was for some type T. In general you would need to provide a definition, I agree. But if you used something from the int family, you wouldn't necessarily have to (with the caveat above).