PR c++/79316 - default argument in deduction guide
PR c++/79350 - explicit deduction guide * parser.c (cp_parser_constructor_declarator_p) (cp_parser_direct_declarator): Parse deduction guides more like constructors. * cp-tree.h (enum special_function_kind): Add sfk_deduction_guide. * tree.c (special_function_p): Return it. * decl.c (check_special_function_return_type): Handle it. (grokdeclarator, grokfndecl): Adjust. (cp_finish_decl): Pass flags to do_auto_deduction. * error.c (dump_decl_name): Use TFF_UNQUALIFIED_NAME. * pt.c (dguide_name_p): Take a const_tree. (do_class_deduction): Handle explicit. (do_auto_deduction): Pass flags through. (build_deduction_guide): Copy explicit flag. From-SVN: r245314
This commit is contained in:
parent
388dde26a5
commit
a56c0ac082
@ -1,3 +1,21 @@
|
||||
2017-02-09 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/79316 - default argument in deduction guide
|
||||
PR c++/79350 - explicit deduction guide
|
||||
* parser.c (cp_parser_constructor_declarator_p)
|
||||
(cp_parser_direct_declarator): Parse deduction guides more like
|
||||
constructors.
|
||||
* cp-tree.h (enum special_function_kind): Add sfk_deduction_guide.
|
||||
* tree.c (special_function_p): Return it.
|
||||
* decl.c (check_special_function_return_type): Handle it.
|
||||
(grokdeclarator, grokfndecl): Adjust.
|
||||
(cp_finish_decl): Pass flags to do_auto_deduction.
|
||||
* error.c (dump_decl_name): Use TFF_UNQUALIFIED_NAME.
|
||||
* pt.c (dguide_name_p): Take a const_tree.
|
||||
(do_class_deduction): Handle explicit.
|
||||
(do_auto_deduction): Pass flags through.
|
||||
(build_deduction_guide): Copy explicit flag.
|
||||
|
||||
2017-02-09 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/79429
|
||||
|
@ -4733,6 +4733,7 @@ enum special_function_kind {
|
||||
deletes the object after it has been
|
||||
destroyed. */
|
||||
sfk_conversion, /* A conversion operator. */
|
||||
sfk_deduction_guide, /* A class template deduction guide. */
|
||||
sfk_inheriting_constructor /* An inheriting constructor */
|
||||
};
|
||||
|
||||
@ -6150,7 +6151,8 @@ extern tree do_auto_deduction (tree, tree, tree);
|
||||
extern tree do_auto_deduction (tree, tree, tree,
|
||||
tsubst_flags_t,
|
||||
auto_deduction_context,
|
||||
tree = NULL_TREE);
|
||||
tree = NULL_TREE,
|
||||
int = LOOKUP_NORMAL);
|
||||
extern tree type_uses_auto (tree);
|
||||
extern tree type_uses_auto_or_concept (tree);
|
||||
extern void append_type_to_template_for_access_check (tree, tree, tree,
|
||||
@ -6280,7 +6282,7 @@ extern tree extract_fnparm_pack (tree, tree *);
|
||||
extern tree template_parm_to_arg (tree);
|
||||
extern tree dguide_name (tree);
|
||||
extern bool dguide_name_p (tree);
|
||||
extern bool deduction_guide_p (tree);
|
||||
extern bool deduction_guide_p (const_tree);
|
||||
|
||||
/* in repo.c */
|
||||
extern void init_repo (void);
|
||||
|
@ -6821,7 +6821,8 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
|
||||
if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
|
||||
adc = adc_decomp_type;
|
||||
type = TREE_TYPE (decl) = do_auto_deduction (type, d_init, auto_node,
|
||||
tf_warning_or_error, adc);
|
||||
tf_warning_or_error, adc,
|
||||
NULL_TREE, flags);
|
||||
if (type == error_mark_node)
|
||||
return;
|
||||
if (TREE_CODE (type) == FUNCTION_TYPE)
|
||||
@ -8730,14 +8731,6 @@ grokfndecl (tree ctype,
|
||||
"namespace scope", decl);
|
||||
return NULL_TREE;
|
||||
}
|
||||
tree type = TREE_TYPE (DECL_NAME (decl));
|
||||
if (CP_DECL_CONTEXT (decl) != CP_TYPE_CONTEXT (type))
|
||||
{
|
||||
error_at (location, "deduction guide %qD must be declared in the "
|
||||
"same scope as %qT", decl, type);
|
||||
inform (location_of (type), " declared here");
|
||||
return NULL_TREE;
|
||||
}
|
||||
if (funcdef_flag)
|
||||
error_at (location,
|
||||
"deduction guide %qD must not have a function body", decl);
|
||||
@ -9758,6 +9751,20 @@ check_special_function_return_type (special_function_kind sfk,
|
||||
type = optype;
|
||||
break;
|
||||
|
||||
case sfk_deduction_guide:
|
||||
if (type)
|
||||
error ("return type specified for deduction guide");
|
||||
else if (type_quals != TYPE_UNQUALIFIED)
|
||||
error_at (smallest_type_quals_location (type_quals, locations),
|
||||
"qualifiers are not allowed on declaration of "
|
||||
"deduction guide");
|
||||
type = make_template_placeholder (CLASSTYPE_TI_TEMPLATE (optype));
|
||||
for (int i = 0; i < ds_last; ++i)
|
||||
if (i != ds_explicit && locations[i])
|
||||
error_at (locations[i],
|
||||
"decl-specifier in declaration of deduction guide");
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
@ -10105,7 +10112,6 @@ grokdeclarator (const cp_declarator *declarator,
|
||||
{
|
||||
gcc_assert (flags == NO_SPECIAL);
|
||||
flags = TYPENAME_FLAG;
|
||||
ctor_return_type = TREE_TYPE (dname);
|
||||
sfk = sfk_conversion;
|
||||
if (is_typename_at_global_scope (dname))
|
||||
name = identifier_to_locale (IDENTIFIER_POINTER (dname));
|
||||
@ -10285,8 +10291,9 @@ grokdeclarator (const cp_declarator *declarator,
|
||||
#endif
|
||||
typedef_type = type;
|
||||
|
||||
|
||||
if (sfk != sfk_conversion)
|
||||
if (sfk == sfk_conversion || sfk == sfk_deduction_guide)
|
||||
ctor_return_type = TREE_TYPE (dname);
|
||||
else
|
||||
ctor_return_type = ctype;
|
||||
|
||||
if (sfk != sfk_none)
|
||||
@ -10906,12 +10913,13 @@ grokdeclarator (const cp_declarator *declarator,
|
||||
if (!late_return_type)
|
||||
{
|
||||
if (dguide_name_p (unqualified_id))
|
||||
error_at (typespec_loc, "deduction guide for "
|
||||
"%qT must have trailing return type",
|
||||
TREE_TYPE (tmpl));
|
||||
error_at (declarator->id_loc, "deduction guide "
|
||||
"for %qT must have trailing return "
|
||||
"type", TREE_TYPE (tmpl));
|
||||
else
|
||||
error_at (typespec_loc, "deduced class type %qT "
|
||||
"in function return type", type);
|
||||
error_at (declarator->id_loc, "deduced class "
|
||||
"type %qT in function return type",
|
||||
type);
|
||||
inform (DECL_SOURCE_LOCATION (tmpl),
|
||||
"%qD declared here", tmpl);
|
||||
}
|
||||
@ -11039,6 +11047,11 @@ grokdeclarator (const cp_declarator *declarator,
|
||||
if (late_return_type_p)
|
||||
error ("a conversion function cannot have a trailing return type");
|
||||
}
|
||||
else if (sfk == sfk_deduction_guide)
|
||||
{
|
||||
if (explicitp == 1)
|
||||
explicitp = 2;
|
||||
}
|
||||
|
||||
arg_types = grokparms (declarator->u.function.parameters,
|
||||
&parms);
|
||||
@ -12207,6 +12220,8 @@ grokdeclarator (const cp_declarator *declarator,
|
||||
if (decl == NULL_TREE)
|
||||
return error_mark_node;
|
||||
|
||||
if (explicitp == 2)
|
||||
DECL_NONCONVERTING_P (decl) = 1;
|
||||
if (staticp == 1)
|
||||
{
|
||||
int invalid_static = 0;
|
||||
|
@ -1015,7 +1015,7 @@ dump_decl_name (cxx_pretty_printer *pp, tree t, int flags)
|
||||
if (dguide_name_p (t))
|
||||
{
|
||||
dump_decl (pp, CLASSTYPE_TI_TEMPLATE (TREE_TYPE (t)),
|
||||
TFF_PLAIN_IDENTIFIER);
|
||||
TFF_UNQUALIFIED_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -19050,26 +19050,9 @@ cp_parser_init_declarator (cp_parser* parser,
|
||||
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
cp_parser_declarator_kind cdk = CP_PARSER_DECLARATOR_NAMED;
|
||||
if (token->type == CPP_OPEN_PAREN
|
||||
&& decl_specifiers->type
|
||||
&& is_auto (decl_specifiers->type)
|
||||
&& CLASS_PLACEHOLDER_TEMPLATE (decl_specifiers->type))
|
||||
{
|
||||
// C++17 deduction guide.
|
||||
cdk = CP_PARSER_DECLARATOR_ABSTRACT;
|
||||
|
||||
for (int i = 0; i < ds_last; ++i)
|
||||
if (i != ds_type_spec
|
||||
&& decl_specifiers->locations[i]
|
||||
&& !cp_parser_simulate_error (parser))
|
||||
error_at (decl_specifiers->locations[i],
|
||||
"decl-specifier in declaration of deduction guide");
|
||||
}
|
||||
|
||||
/* Parse the declarator. */
|
||||
declarator
|
||||
= cp_parser_declarator (parser, cdk,
|
||||
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
|
||||
&ctor_dtor_or_conv_p,
|
||||
/*parenthesized_p=*/NULL,
|
||||
member_p, friend_p);
|
||||
@ -19083,17 +19066,6 @@ cp_parser_init_declarator (cp_parser* parser,
|
||||
if (declarator == cp_error_declarator)
|
||||
return error_mark_node;
|
||||
|
||||
if (cdk == CP_PARSER_DECLARATOR_ABSTRACT)
|
||||
{
|
||||
gcc_assert (declarator->kind == cdk_function
|
||||
&& !declarator->declarator);
|
||||
tree t = CLASS_PLACEHOLDER_TEMPLATE (decl_specifiers->type);
|
||||
declarator->declarator = make_id_declarator (NULL_TREE, dguide_name (t),
|
||||
sfk_none);
|
||||
declarator->declarator->id_loc
|
||||
= decl_specifiers->locations[ds_type_spec];
|
||||
}
|
||||
|
||||
/* Check that the number of template-parameter-lists is OK. */
|
||||
if (!cp_parser_check_declarator_template_parameters (parser, declarator,
|
||||
token->location))
|
||||
@ -19136,6 +19108,25 @@ cp_parser_init_declarator (cp_parser* parser,
|
||||
|
||||
if (function_declarator_p (declarator))
|
||||
{
|
||||
/* Handle C++17 deduction guides. */
|
||||
if (!decl_specifiers->type
|
||||
&& ctor_dtor_or_conv_p <= 0
|
||||
&& cxx_dialect >= cxx1z)
|
||||
{
|
||||
cp_declarator *id = get_id_declarator (declarator);
|
||||
tree name = id->u.id.unqualified_name;
|
||||
parser->scope = id->u.id.qualifying_scope;
|
||||
tree tmpl = cp_parser_lookup_name_simple (parser, name, id->id_loc);
|
||||
if (tmpl
|
||||
&& (DECL_CLASS_TEMPLATE_P (tmpl)
|
||||
|| DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))
|
||||
{
|
||||
id->u.id.unqualified_name = dguide_name (tmpl);
|
||||
id->u.id.sfk = sfk_deduction_guide;
|
||||
ctor_dtor_or_conv_p = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if the token indicates the start of a
|
||||
function-definition. */
|
||||
if (cp_parser_token_starts_function_definition_p (token))
|
||||
@ -19202,8 +19193,8 @@ cp_parser_init_declarator (cp_parser* parser,
|
||||
|
||||
/* [dcl.dcl]
|
||||
|
||||
Only in function declarations for constructors, destructors, and
|
||||
type conversions can the decl-specifier-seq be omitted.
|
||||
Only in function declarations for constructors, destructors, type
|
||||
conversions, and deduction guides can the decl-specifier-seq be omitted.
|
||||
|
||||
We explicitly postpone this check past the point where we handle
|
||||
function-definitions because we tolerate function-definitions
|
||||
@ -19453,8 +19444,8 @@ cp_parser_init_declarator (cp_parser* parser,
|
||||
attributes [opt] direct-abstract-declarator
|
||||
|
||||
If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to
|
||||
detect constructor, destructor or conversion operators. It is set
|
||||
to -1 if the declarator is a name, and +1 if it is a
|
||||
detect constructors, destructors, deduction guides, or conversion operators.
|
||||
It is set to -1 if the declarator is a name, and +1 if it is a
|
||||
function. Otherwise it is set to zero. Usually you just want to
|
||||
test for >0, but internally the negative value is used.
|
||||
|
||||
@ -25929,8 +25920,8 @@ cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p)
|
||||
}
|
||||
|
||||
/* Returns TRUE if the upcoming token sequence is the start of a
|
||||
constructor declarator. If FRIEND_P is true, the declarator is
|
||||
preceded by the `friend' specifier. */
|
||||
constructor declarator or C++17 deduction guide. If FRIEND_P is true, the
|
||||
declarator is preceded by the `friend' specifier. */
|
||||
|
||||
static bool
|
||||
cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
|
||||
@ -25975,8 +25966,10 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
|
||||
|| friend_p);
|
||||
|
||||
/* Outside of a class-specifier, there must be a
|
||||
nested-name-specifier. */
|
||||
if (!nested_name_specifier && outside_class_specifier_p)
|
||||
nested-name-specifier. Except in C++17 mode, where we
|
||||
might be declaring a guiding declaration. */
|
||||
if (!nested_name_specifier && outside_class_specifier_p
|
||||
&& cxx_dialect < cxx1z)
|
||||
constructor_p = false;
|
||||
else if (nested_name_specifier == error_mark_node)
|
||||
constructor_p = false;
|
||||
@ -26007,6 +26000,9 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
|
||||
};
|
||||
|
||||
we must recognize that the nested `S' names a class. */
|
||||
if (cxx_dialect >= cxx1z)
|
||||
cp_parser_parse_tentatively (parser);
|
||||
|
||||
tree type_decl;
|
||||
type_decl = cp_parser_class_name (parser,
|
||||
/*typename_keyword_p=*/false,
|
||||
@ -26015,6 +26011,24 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
|
||||
/*check_dependency_p=*/false,
|
||||
/*class_head_p=*/false,
|
||||
/*is_declaration=*/false);
|
||||
|
||||
if (cxx_dialect >= cxx1z
|
||||
&& !cp_parser_parse_definitely (parser))
|
||||
{
|
||||
type_decl = NULL_TREE;
|
||||
tree tmpl = cp_parser_template_name (parser,
|
||||
/*template_keyword*/false,
|
||||
/*check_dependency_p*/false,
|
||||
/*is_declaration*/false,
|
||||
none_type,
|
||||
/*is_identifier*/NULL);
|
||||
if (DECL_CLASS_TEMPLATE_P (tmpl)
|
||||
|| DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
|
||||
/* It's a deduction guide, return true. */;
|
||||
else
|
||||
cp_parser_simulate_error (parser);
|
||||
}
|
||||
|
||||
/* If there was no class-name, then this is not a constructor.
|
||||
Otherwise, if we are in a class-specifier and we aren't
|
||||
handling a friend declaration, check that its type matches
|
||||
@ -26022,6 +26036,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
|
||||
is left alone for error recovery purposes. */
|
||||
constructor_p = (!cp_parser_error_occurred (parser)
|
||||
&& (outside_class_specifier_p
|
||||
|| type_decl == NULL_TREE
|
||||
|| type_decl == error_mark_node
|
||||
|| same_type_p (current_class_type,
|
||||
TREE_TYPE (type_decl))));
|
||||
@ -26056,7 +26071,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
|
||||
in the scope of the class. */
|
||||
if (current_class_type)
|
||||
type = NULL_TREE;
|
||||
else
|
||||
else if (type_decl)
|
||||
{
|
||||
type = TREE_TYPE (type_decl);
|
||||
if (TREE_CODE (type) == TYPENAME_TYPE)
|
||||
|
58
gcc/cp/pt.c
58
gcc/cp/pt.c
@ -24786,7 +24786,7 @@ dguide_name_p (tree name)
|
||||
/* True if FN is a deduction guide. */
|
||||
|
||||
bool
|
||||
deduction_guide_p (tree fn)
|
||||
deduction_guide_p (const_tree fn)
|
||||
{
|
||||
if (DECL_P (fn))
|
||||
if (tree name = DECL_NAME (fn))
|
||||
@ -24999,6 +24999,7 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
|
||||
dguide_name (type), fntype);
|
||||
DECL_ARGUMENTS (ded_fn) = fargs;
|
||||
DECL_ARTIFICIAL (ded_fn) = true;
|
||||
DECL_NONCONVERTING_P (ded_fn) = DECL_NONCONVERTING_P (ctor);
|
||||
tree ded_tmpl = build_template_decl (ded_fn, tparms, /*member*/false);
|
||||
DECL_ARTIFICIAL (ded_tmpl) = true;
|
||||
DECL_TEMPLATE_RESULT (ded_tmpl) = ded_fn;
|
||||
@ -25015,8 +25016,9 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
|
||||
template TMPL based on the initializer INIT, and return the resulting
|
||||
type. */
|
||||
|
||||
tree
|
||||
do_class_deduction (tree ptype, tree tmpl, tree init, tsubst_flags_t complain)
|
||||
static tree
|
||||
do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
|
||||
tsubst_flags_t complain)
|
||||
{
|
||||
if (!DECL_CLASS_TEMPLATE_P (tmpl))
|
||||
{
|
||||
@ -25083,9 +25085,48 @@ do_class_deduction (tree ptype, tree tmpl, tree init, tsubst_flags_t complain)
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* Prune explicit deduction guides in copy-initialization context. */
|
||||
tree old_cands = cands;
|
||||
if (flags & LOOKUP_ONLYCONVERTING)
|
||||
{
|
||||
tree t = cands;
|
||||
for (; t; t = OVL_NEXT (t))
|
||||
if (DECL_NONCONVERTING_P (DECL_TEMPLATE_RESULT (OVL_CURRENT (t))))
|
||||
break;
|
||||
if (t)
|
||||
{
|
||||
tree pruned = NULL_TREE;
|
||||
for (t = cands; t; t = OVL_NEXT (t))
|
||||
{
|
||||
tree f = OVL_CURRENT (t);
|
||||
if (!DECL_NONCONVERTING_P (DECL_TEMPLATE_RESULT (f)))
|
||||
pruned = build_overload (f, pruned);
|
||||
}
|
||||
cands = pruned;
|
||||
if (cands == NULL_TREE)
|
||||
{
|
||||
error ("cannot deduce template arguments for copy-initialization"
|
||||
" of %qT, as it has no non-explicit deduction guides or "
|
||||
"user-declared constructors", type);
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++cp_unevaluated_operand;
|
||||
tree t = build_new_function_call (cands, &args, /*koenig*/false,
|
||||
complain|tf_decltype);
|
||||
tf_decltype);
|
||||
|
||||
if (t == error_mark_node && (complain & tf_warning_or_error))
|
||||
{
|
||||
error ("class template argument deduction failed:");
|
||||
t = build_new_function_call (cands, &args, /*koenig*/false,
|
||||
complain | tf_decltype);
|
||||
if (old_cands != cands)
|
||||
inform (input_location, "explicit deduction guides not considered "
|
||||
"for copy-initialization");
|
||||
}
|
||||
|
||||
--cp_unevaluated_operand;
|
||||
release_tree_vector (args);
|
||||
|
||||
@ -25106,7 +25147,10 @@ do_auto_deduction (tree type, tree init, tree auto_node)
|
||||
/* Replace occurrences of 'auto' in TYPE with the appropriate type deduced
|
||||
from INIT. AUTO_NODE is the TEMPLATE_TYPE_PARM used for 'auto' in TYPE.
|
||||
The CONTEXT determines the context in which auto deduction is performed
|
||||
and is used to control error diagnostics.
|
||||
and is used to control error diagnostics. FLAGS are the LOOKUP_* flags.
|
||||
OUTER_TARGS are used during template argument deduction
|
||||
(context == adc_unify) to properly substitute the result, and is ignored
|
||||
in other contexts.
|
||||
|
||||
For partial-concept-ids, extra args may be appended to the list of deduced
|
||||
template arguments prior to determining constraint satisfaction. */
|
||||
@ -25114,7 +25158,7 @@ do_auto_deduction (tree type, tree init, tree auto_node)
|
||||
tree
|
||||
do_auto_deduction (tree type, tree init, tree auto_node,
|
||||
tsubst_flags_t complain, auto_deduction_context context,
|
||||
tree outer_targs)
|
||||
tree outer_targs, int flags)
|
||||
{
|
||||
tree targs;
|
||||
|
||||
@ -25129,7 +25173,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
|
||||
|
||||
if (tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node))
|
||||
/* C++17 class template argument deduction. */
|
||||
return do_class_deduction (type, tmpl, init, complain);
|
||||
return do_class_deduction (type, tmpl, init, flags, complain);
|
||||
|
||||
/* [dcl.spec.auto]: Obtain P from T by replacing the occurrences of auto
|
||||
with either a new invented type template parameter U or, if the
|
||||
|
@ -4374,6 +4374,8 @@ special_function_p (const_tree decl)
|
||||
return sfk_deleting_destructor;
|
||||
if (DECL_CONV_FN_P (decl))
|
||||
return sfk_conversion;
|
||||
if (deduction_guide_p (decl))
|
||||
return sfk_deduction_guide;
|
||||
|
||||
return sfk_none;
|
||||
}
|
||||
|
5
gcc/testsuite/g++.dg/cpp1z/class-deduction27.C
Normal file
5
gcc/testsuite/g++.dg/cpp1z/class-deduction27.C
Normal file
@ -0,0 +1,5 @@
|
||||
// PR c++/79316
|
||||
// { dg-options -std=c++1z }
|
||||
|
||||
template<typename T> struct S { S(T t) {} };
|
||||
template<typename T> S(T, int = 7) -> S<T>;
|
24
gcc/testsuite/g++.dg/cpp1z/class-deduction28.C
Normal file
24
gcc/testsuite/g++.dg/cpp1z/class-deduction28.C
Normal file
@ -0,0 +1,24 @@
|
||||
// PR c++/79350
|
||||
// { dg-options -std=c++1z }
|
||||
|
||||
template <class T>
|
||||
struct A
|
||||
{
|
||||
explicit A(T);
|
||||
};
|
||||
|
||||
|
||||
A a (42);
|
||||
A a2 = 42; // { dg-error "" }
|
||||
|
||||
template <class T>
|
||||
struct B
|
||||
{
|
||||
B(T*);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
explicit B(T) -> B<T*>;
|
||||
|
||||
B b1 (0);
|
||||
B b2 = 0; // { dg-error "" }
|
@ -10,7 +10,7 @@ namespace N {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
N::A(T) -> N::A<T>; // { dg-error "scope" }
|
||||
N::A(T) -> N::A<T>; // { dg-error "should have been declared inside .N" }
|
||||
|
||||
namespace N {
|
||||
template <class T>
|
||||
|
Loading…
Reference in New Issue
Block a user