Bug 88252 - Deduction guide assume the constructor parameter is a forwarding reference if constructor defined outside class
Summary: Deduction guide assume the constructor parameter is a forwarding reference if...
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 8.2.1
: P3 normal
Target Milestone: 12.0
Assignee: Patrick Palka
Keywords: accepts-invalid, rejects-valid
Depends on:
Reported: 2018-11-28 19:58 UTC by Olivier Kannengieser
Modified: 2022-03-21 12:14 UTC (History)
3 users (show)

See Also:
Known to work:
Known to fail:
Last reconfirmed: 2020-09-16 00:00:00


Note You need to log in before you can comment on or make changes to this bug.
Description Olivier Kannengieser 2018-11-28 19:58:44 UTC
Constructor parameter that have the forms of a forwarding reference (T&&) inside a constructor are not forwarding reference if T is a parameter of the class template. But gcc assumes it is a forwarding reference if the constructor is defined outside the class:

template<typename T>
struct B1 {
    B1(T&& x){}

template<typename T>
struct B2 {
    B2(T&& x) ;
template<typename T>
B2<T>::B2(T&& x){}

int i;
B1 a{i};//Expect: compilation error, class template argument deduction failed
B2 b{i};//Unexpected: no compilation error.
Comment 1 GCC Commits 2021-07-14 19:38:23 UTC
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>:


commit r12-2309-gbebd8e9da838c51a7f911985083d5a2b2498a23a
Author: Patrick Palka <ppalka@redhat.com>
Date:   Wed Jul 14 15:37:30 2021 -0400

    c++: CTAD and forwarding references [PR88252]
    Here during CTAD we're incorrectly treating T&& as a forwarding
    reference even though T is a template parameter of the class template.
    This happens because the template parameter T in the out-of-line
    definition of the constructor doesn't have the flag
    TEMPLATE_TYPE_PARM_FOR_CLASS set, and during duplicate_decls the
    the redeclaration (which is in terms of this unflagged T) prevails.
    To fix this, we could perhaps be more consistent about setting the flag,
    but it appears we don't really need this flag to make the determination.
    Since the template parameters of an synthesized guide consist of the
    template parameters of the class template followed by those of the
    constructor (if any), it should suffice to look at the index of the
    template parameter to determine whether it comes from the class
    template or the constructor (template).  This patch replaces the
    TEMPLATE_TYPE_PARM_FOR_CLASS flag with this approach.
            PR c++/88252
            * cp-tree.h (TEMPLATE_TYPE_PARM_FOR_CLASS): Remove.
            * pt.c (push_template_decl): Remove TEMPLATE_TYPE_PARM_FOR_CLASS
            (redeclare_class_template): Likewise.
            (forwarding_reference_p): Define.
            (maybe_adjust_types_for_deduction): Use it instead.  Add 'tparms'
            (unify_one_argument): Pass tparms to
            (try_one_overload): Likewise.
            (unify): Likewise.
            (rewrite_template_parm): Remove TEMPLATE_TYPE_PARM_FOR_CLASS
            * g++.dg/cpp1z/class-deduction96.C: New test.
Comment 2 Patrick Palka 2022-03-21 12:14:24 UTC
Fixed for GCC 12