Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructor selection precedence in a C++ class

Tags:

c++

Please help with this sample code:

struct A
{
   std::string value;
  
   A() {}
   A(A const &) {}
  
   template <typename... Args>
   A(Args&&... args) : value (std::forward<Args>(args)...) {}
};
  
int main(void)
{
   auto a = A();
   auto b = a;
  
   return 0;
}

An error is thrown while compiling:

error: no matching function for call to ‘std::__cxx11::basic_string<char>::basic_string(A&)’

For some reason the compiler wants to call the templated constructor even though the class has a copy constructor. So the question is - why the compiler does not see copy constructor?

like image 989
Vyacheslav Lavrentev Avatar asked Sep 12 '26 20:09

Vyacheslav Lavrentev


1 Answers

In your example, the template constructor is a better match than the non-template constructor because of the universal reference the template constructor uses, which allows the compiler to pass the lvalue a to the constructor as-is, whilst the non-template one requires it to be a const lvalue.

If instead of declaring a like this:

auto a = A();

You declared it like this

const auto a = A();

Then the copy constructor would be chosen instead, since it would be a better match.

To make your example work, you will need to use SFINAE or concepts (if using at least C++20).

With SFINAE:

struct A
{
   std::string value;
  
   A() {}
   A(A const &) {}
  
   template <typename Arg, typename... Args,
        std::enable_if_t<!std::is_same_v<A, std::remove_reference_t<Arg>>>* = nullptr>
    A(Arg &&arg, Args&&... args): value (std::forward<Arg>(arg), std::forward<Args>(args)...) {}
};

With concepts:

struct A
{
   std::string value;
  
   A() {}
   A(A const &) {}
  
    template <typename Arg, typename... Args>
    requires (!std::same_as<A, std::remove_reference_t<Arg>>)
    A(Arg &&arg, Args&&... args): value (std::forward<Arg>(arg), std::forward<Args>(args)...) {}
};
like image 84
Fabio A. Avatar answered Sep 14 '26 09:09

Fabio A.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!