c++: prefer 'emplace' to 'build'

When we introduced variants in Bison, C++ did not have the 'emplace'
functions, and we chose 'build'.  Let's align with modern C++ and
promote 'emplace' rather than 'build'.

* data/lalr1.cc, data/variant.hh (emplace): New.
(build): Deprecate in favor of emplace.
* doc/bison.texi: Adjust.
This commit is contained in:
Akim Demaille
2018-10-20 10:32:27 +02:00
parent e7b709ab0b
commit 42f0b949ec
3 changed files with 30 additions and 12 deletions

View File

@@ -862,7 +862,7 @@ b4_dollar_popdef])[]dnl
/* Variants are always initialized to an empty instance of the /* Variants are always initialized to an empty instance of the
correct type. The default '$$ = $1' action is NOT applied correct type. The default '$$ = $1' action is NOT applied
when using variants. */ when using variants. */
b4_symbol_variant([[yyr1_@{yyn@}]], [yylhs.value], [build])], [ b4_symbol_variant([[yyr1_@{yyn@}]], [yylhs.value], [emplace])], [
/* If YYLEN is nonzero, implement the default value of the /* If YYLEN is nonzero, implement the default value of the
action: '$$ = $1'. Otherwise, use the top of the stack. action: '$$ = $1'. Otherwise, use the top of the stack.

View File

@@ -117,7 +117,7 @@ m4_define([b4_variant_define],
/// Instantiate an empty \a T in here. /// Instantiate an empty \a T in here.
template <typename T> template <typename T>
T& T&
build () emplace ()
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (!yytypeid_); YYASSERT (!yytypeid_);
YYASSERT (sizeof (T) <= S); YYASSERT (sizeof (T) <= S);
@@ -128,7 +128,7 @@ m4_define([b4_variant_define],
/// Instantiate a \a T in here from \a t. /// Instantiate a \a T in here from \a t.
template <typename T> template <typename T>
T& T&
build (const T& t) emplace (const T& t)
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (!yytypeid_); YYASSERT (!yytypeid_);
YYASSERT (sizeof (T) <= S); YYASSERT (sizeof (T) <= S);
@@ -136,6 +136,24 @@ m4_define([b4_variant_define],
return *new (yyas_<T> ()) T (t); return *new (yyas_<T> ()) T (t);
} }
/// Instantiate an empty \a T in here.
/// Obsolete, use emplace.
template <typename T>
T&
build ()
{
return emplace<T> ();
}
/// Instantiate a \a T in here from \a t.
/// Obsolete, use emplace.
template <typename T>
T&
build (const T& t)
{
return emplace<T> (t);
}
/// Accessor to a built \a T. /// Accessor to a built \a T.
template <typename T> template <typename T>
T& T&
@@ -182,7 +200,7 @@ m4_define([b4_variant_define],
void void
move (self_type& other) move (self_type& other)
{ {
build<T> (); emplace<T> ();
# if defined __cplusplus && 201103L <= __cplusplus # if defined __cplusplus && 201103L <= __cplusplus
as<T> () = std::move (other.as<T> ()); as<T> () = std::move (other.as<T> ());
# else # else
@@ -197,7 +215,7 @@ m4_define([b4_variant_define],
void void
move (self_type&& other) move (self_type&& other)
{ {
build<T> (); emplace<T> ();
as<T> () = std::move (other.as<T> ()); as<T> () = std::move (other.as<T> ());
other.destroy<T> (); other.destroy<T> ();
} }
@@ -208,7 +226,7 @@ m4_define([b4_variant_define],
void void
copy (const self_type& other) copy (const self_type& other)
{ {
build<T> (other.as<T> ()); emplace<T> (other.as<T> ());
} }
/// Destroy the stored \a T. /// Destroy the stored \a T.

View File

@@ -10835,12 +10835,12 @@ of alternative types such as @samp{$<int>2} or @samp{$<std::string>$}, even
in midrule actions. It is mandatory to use typed midrule actions in midrule actions. It is mandatory to use typed midrule actions
(@pxref{Typed Midrule Actions}). (@pxref{Typed Midrule Actions}).
@deftypemethod {semantic_type} {T&} build<T> () @deftypemethod {semantic_type} {T&} emplace<T> ()
Initialize, but leave empty. Returns the address where the actual value may Initialize, but leave empty. Returns the address where the actual value may
be stored. Requires that the variant was not initialized yet. be stored. Requires that the variant was not initialized yet.
@end deftypemethod @end deftypemethod
@deftypemethod {semantic_type} {T&} build<T> (const T& @var{t}) @deftypemethod {semantic_type} {T&} emplace<T> (const T& @var{t})
Initialize, and copy-construct from @var{t}. Initialize, and copy-construct from @var{t}.
@end deftypemethod @end deftypemethod
@@ -11166,11 +11166,11 @@ initialized. So the code would look like:
@example @example
[0-9]+ @{ [0-9]+ @{
yylval->build<int> () = text_to_int (yytext); yylval->emplace<int> () = text_to_int (yytext);
return yy::parser::token::INTEGER; return yy::parser::token::INTEGER;
@} @}
[a-z]+ @{ [a-z]+ @{
yylval->build<std::string> () = yytext; yylval->emplace<std::string> () = yytext;
return yy::parser::token::IDENTIFIER; return yy::parser::token::IDENTIFIER;
@} @}
@end example @end example
@@ -11180,11 +11180,11 @@ or
@example @example
[0-9]+ @{ [0-9]+ @{
yylval->build (text_to_int (yytext)); yylval->emplace (text_to_int (yytext));
return yy::parser::token::INTEGER; return yy::parser::token::INTEGER;
@} @}
[a-z]+ @{ [a-z]+ @{
yylval->build (yytext); yylval->emplace (yytext);
return yy::parser::token::IDENTIFIER; return yy::parser::token::IDENTIFIER;
@} @}
@end example @end example