Home > Mobile >  Defining default constructor results in C2600 {cannot define a compiler-generated special member fun
Defining default constructor results in C2600 {cannot define a compiler-generated special member fun

Time:11-25

I'm learning 'modern' C and I'm having a really hard time discerning the issue with this code.

Ball.h:

#ifndef BALL_H
#define BALL_H
#include <string>
#include <string_view>

namespace ball
{
    class Ball
    {
        std::string _color{};
        double _radius{};

    public:

        Ball() = default;
        Ball(double radius);
        Ball(std::string_view color = "black", double radius = 10);

        void print() const;
    };
}

#endif // !BALL_H

Ball.cpp:

#include "Ball.h"
#include <iostream>
#include <string_view>

namespace ball
{
    Ball::Ball(double radius)
    {
        _color = "black";
        _radius = radius;
    }

    Ball::Ball(std::string_view color, double radius)
    {
        _color = color;
        _radius = radius;
    }

    void Ball::print() const
    {
        std::cout << "Ball: " << std::endl;
        std::cout << "\tcolor: " << _color << std::endl;
        std::cout << "\tradius: " << _radius << std::endl;
    }

}

Why does defining Ball() = default; produce a compiler error (complaining about the constructor that takes two arguments, causing further confusion).

If I omit the default constructor definition entirely the code compiles and functions perfectly fine.

I wish I could be more descriptive, but I'm at a loss here.

CodePudding user response:

Edit

It turned out the actual error in the title C2600 is emitted mistakenly. The answer below still holds, but it's not directly relevant to the described issue, please refer to user17732522's answer for more details.


The problem here is that both arguments in the Ball(std::string_view, double) constructor can be omitted (as they got default values) and there is no way for the compiler to distinguish this constructor from Ball() when the client code relies on a constructor without arguments (having such constructors declared on it's own is not an error, the problem comes at function candidate resolution step):

Ball a; // Ball() or Ball(std::string_view, double) with default arguments?

Thus you will have to leave only one of these two constructors for the class to be default-constructible:

class Ball
{
    ...

public:

    Ball(double radius);
    // all good now. This constructor is used to default-construct the class
    Ball(std::string_view color = "black", double radius = 10);

    ...
};

CodePudding user response:

The particular error message you are referencing seems to be generated only by older MSVC versions (<= v19.31).

It clearly looks like a bug in the compiler to me that has been fixed in later versions. When determining which in-class declaration the out-of-class definition matches, the parameter types should be compared for equivalency irregardless of default arguments. Therefore your definition matches the overload with two parameters, not the defaulted one without any.

However, the constructors are not useful with this overload set, as pointed out by the other answer. It will fail as soon as you try to default-construct an object because both overloads would be equally good fits for the initialization in overload resolution, resulting in ambiguity.

  • Related