Skip to content

[class.copy.ctor] Class.copy.ctor doesn't distintuish between two class types formed inside a class template #904

@ranaanoop

Description

@ranaanoop

Full name of submitter: Anoop S. Rana

Reference (section label): class.copy.ctor

Link to reflector thread: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101113

Issue description: Consider the following program that is rejected by gcc and clang but accepted by msvc. The intention seems to make it ill-formed as also discussed in the old gcc bug report that also says this should/is ill-formed. Demo

//let's call this program 1
#include <concepts>

template <typename T>
class A {
    A(A<void>) requires (!std::same_as<void, T>){}
};

In class.copy.ctor we have:

A declaration of a constructor for a class X is ill-formed if its first parameter is of type cv X and either there are no other parameters or else all other parameters have default arguments. A member function template is never instantiated to produce such a constructor signature.

It isn't clear how the above quoted reference from class.copy.ctor says that the class types X<T> and X<void> are same. I mean for the class template A in our example, the copy ctor should be formed using X<T> and not X<void> so that the ctor version with X<void> parameter can be a parameterized ctor with a parameter of type X<void> and not a copy ctor. I mean it depends on what T will be. We can already have program like this:

//let's call this program 2
template <typename T>
struct A {
     
    A(A<T>&){
        std::cout << "inside A<T>" ;
    }
    A(A<void>&){std::cout << "inside A<void>";}
    
    A(){std::cout << "inside default ctor\n";}
};
void f(A<int>)
{

}
 A<int> i;
 int main()
 {
    f(i); //calls A<T> version 
 }

where the output depends on which class tempalte we instantiate. So the program 1 should also work depending upon T instead of not work for all types. I mean in program 2 it is clear the T will determine which version to use so why isn't T also determining the result in case of program 1. One reason might be to reduce complexity of the language wording etc the wording is so choosen for reason like the ill-formedness should not depend on T but that doesn't make much sense to me.

Suggested resolution: We should add wording to make this well-formed depending on T instead of putting a blanket ban for all T.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions