diff --git a/NEWS b/NEWS index 3b714d6a..5f23fa79 100644 --- a/NEWS +++ b/NEWS @@ -100,6 +100,22 @@ GNU Bison NEWS until it sees the '='. So we notate the two possible reductions to indicate that each conflicts in one rule. +*** C++: Variadic emplace + + If your application requires C++11, you may now use a variadic emplace for + semantic values: + + %define api.value.type variant + %token > PAIR + + in your scanner: + + int yylex (parser::semantic_type *lvalp) + { + lvalp->emplace > (1, 2); + return parser::token::PAIR; + } + *** More POSIX Yacc compatibility warnings More Bison specific directives are now reported with -y or -Wyacc. This diff --git a/data/variant.hh b/data/variant.hh index 3264528a..47ff9cbd 100644 --- a/data/variant.hh +++ b/data/variant.hh @@ -121,6 +121,18 @@ m4_define([b4_value_type_declare], YYASSERT (!yytypeid_); ])[} +# if 201103L <= YY_CPLUSPLUS + /// Instantiate a \a T in here from \a t. + template + T& + emplace (U&&... u) + {]b4_parse_assert_if([ + YYASSERT (!yytypeid_); + YYASSERT (sizeof (T) <= size); + yytypeid_ = & typeid (T);])[ + return *new (yyas_ ()) T (std::forward (u)...); + } +# else /// Instantiate an empty \a T in here. template T& @@ -132,18 +144,6 @@ m4_define([b4_value_type_declare], return *new (yyas_ ()) T (); } -# if 201103L <= YY_CPLUSPLUS - /// Instantiate a \a T in here from \a t. - template - T& - emplace (U&& u) - {]b4_parse_assert_if([ - YYASSERT (!yytypeid_); - YYASSERT (sizeof (T) <= size); - yytypeid_ = & typeid (T);])[ - return *new (yyas_ ()) T (std::forward (u)); - } -# else /// Instantiate a \a T in here from \a t. template T& diff --git a/doc/bison.texi b/doc/bison.texi index 8a66236d..e20ae028 100644 --- a/doc/bison.texi +++ b/doc/bison.texi @@ -11088,20 +11088,17 @@ in midrule actions. It is mandatory to use typed midrule actions (@pxref{Typed Midrule Actions}). @deftypemethod {semantic_type} {T&} emplace () -Initialize, but leave empty. Return a reference to where the actual value -may be stored. Requires that the variant was not initialized yet. +@deftypemethodx {semantic_type} {T&} emplace (const T& @var{t}) +Available in C++98/C++03 only. Default construct/copy-construct from +@var{t}. Return a reference to where the actual value may be stored. +Requires that the variant was not initialized yet. @end deftypemethod -@deftypemethod {semantic_type} {T&} emplace (const T& @var{t}) -Initialize, and copy-construct from @var{t}. Available in C++98/C++03 only. +@deftypemethod {semantic_type} {T&} emplace (U&&... @var{u}) +Available in C++11 and later only. Build a variant of type @code{T} from +the variadic forwarding references @var{u...}. @end deftypemethod -@deftypemethod {semantic_type} {T&} emplace (U&& @var{u}) -Build a variant of type @code{T} from the forwarding reference @var{u}. -Available in C++11 and later only. -@end deftypemethod - - @strong{Warning}: We do not use Boost.Variant, for two reasons. First, it appeared unacceptable to require Boost on the user's machine (i.e., the machine on which the generated parser will be compiled, not the machine on diff --git a/tests/types.at b/tests/types.at index a2758917..1bbb958d 100644 --- a/tests/types.at +++ b/tests/types.at @@ -288,21 +288,22 @@ m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]], AT_VAL.build (std::make_pair ("two", "deux"));], [10:11, two:deux]) - # Move-only types. + # Move-only types, and variadic emplace. AT_TEST([%skeleton "]b4_skel[" %code requires { #include } %define api.value.type variant], [[%token > '1'; - %token > '2';]], - ['1' '2' { std::cout << *$1 << ", " << *$2 << '\n'; }], + %token > '2';]], + ['1' '2' { std::cout << *$1 << ", " + << $2.first << ", " + << $2.second << '\n'; }], ["12"], [[if (res == '1') ]AT_VAL[.emplace > (std::make_unique (10)); else if (res == '2') - ]AT_VAL[.emplace > - (std::make_unique ("two"));]], - [10, two], + ]AT_VAL[.emplace > (21, 22);]], + [10, 21, 22], [AT_REQUIRE_CXX_STD(14, [echo "$at_std not supported"; continue])])]) ]) ])