What is the name of this unusual C ++ template function used by Boost.Spirit?

Below is the code from the Boost.Spirit x3 documentation . It uses an interesting C ++ syntax that I have never seen before, which is almost impossible to describe in a search query without knowing the correct terminology. Is this a shorthand for direct class declaration? Where is this function mentioned in the C ++ standard?

namespace parser { using x3::eps; using x3::lit; using x3::_val; using x3::_attr; using ascii::char_; auto set_zero = [&](auto& ctx){ _val(ctx) = 0; }; auto add1000 = [&](auto& ctx){ _val(ctx) += 1000; }; auto add = [&](auto& ctx){ _val(ctx) += _attr(ctx); }; // What is this? This is the very first use of the identifier `roman`. x3::rule<class roman, unsigned> const roman = "roman"; // ^^^^^^^^^^^ auto const roman_def = eps [set_zero] >> ( -(+lit('M') [add1000]) >> -hundreds [add] >> -tens [add] >> -ones [add] ) ; BOOST_SPIRIT_DEFINE(roman); } 
+50
c ++ language-lawyer c ++ 11 templates boost-spirit
Aug 31 '16 at 0:12
source share
2 answers

Template arguments do not have to be defined for use. Using "class roman" actually declares a roman class.

Here is a sample code:

 #include <iostream> template <class T> void foo(); template<> void foo<class roman>() { // allowed because roman is declared roman* pointer1; // not allowed because romania is not declared // romania* pointer2; std::cout << "Hello world!" << std::endl; return; } int main(int argc, char** argv) { return 0; } 

As people noted in the comments above, this is what sets this template instance apart. And for a direct answer to the question that you had, specifying the nature of the template argument in instantiating the template is called a "specified type specifier".

+40
Aug 31 '16 at 0:30
source share

This is the same as:

 class roman; x3::rule<roman, unsigned> const roman = "roman"; 

In other words, writing class T where the type name is expected, first declares that T is the class name, and then goes to T as the type name used for the rest of the expression.

Note that in C ++ there is no collision between typename roman and the variable name roman declared here; It is allowed.




Another case of this can happen without patterns, for example:

 void func( class bar *ptr ); 

is correct if bar not declared; it declares bar , and then declares a function to point to a pointer to bar .

+27
Aug 31 '16 at 1:38
source share



All Articles