2

For the following code:

struct S
{
    S() = default;
    S(S const&) = default;
    S(S&&) = default;

    S& operator=(S const& other) = default;
    S& operator=(S&&) = default;

    template <typename... T>
    S(T&&... params)
    {
    }
};

int main()
{
    S s;
    return 0;
}

I get an error message:

Error C2580 'S::S(void)': multiple versions of a defaulted special member functions are not allowed

Whic I don't understand. I think that the error is caused by the templated constructor (Verified this by commenting it out and got the program compiled).

Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
Peter Lenkefi
  • 1,306
  • 11
  • 29
  • I guess `S(S&&);` should have custom implementation. Because this is the function in which you steal away the memory area (i.e data) of the parameter that is passed to it. Otherwise it would be same as `S(S const&);` Same would apply to `operator=` – sameerkn May 13 '16 at 06:18
  • A `main()` that actually exercises this to the point of your compile error would make this question considerably more robust. Perhaps update the question. – WhozCraig May 13 '16 at 06:24
  • 1
    Your templated constructor can be the same as any of your defaulted constructors, so the compiler doesn't know what you want to do. It can be a default, copy, or move constructor. You said you want it default, but you also provide a custom implementation. – xaxxon May 13 '16 at 06:25
  • @xaxxon when two or more constructors match equally good, a non-template is preferred in overload resolution – Piotr Skotnicki May 13 '16 at 06:36
  • @PiotrSkotnicki this seems a much more specific error. Also, this is VS we're talking about, so standards don't mean too much. – xaxxon May 13 '16 at 06:38
  • Cannot reproduce. (You can test Visual C++ Compiler [here](http://webcompiler.cloudapp.net/)) – kakkoko May 13 '16 at 06:43
  • @xaxxon *"this seems a much more specific error"*, what ? – Piotr Skotnicki May 13 '16 at 06:43
  • What version of VS are you using? – xaxxon May 13 '16 at 06:45
  • @xaxxon Using VS 2015 Update 2 – Peter Lenkefi May 13 '16 at 07:02
  • Are you using the 2015 toolchain? meaning you didn't tell vs2015 to build with the vs2013 toolset? Because like @kakkoko said, it's not reproduceable with the code you posted. Can YOU reproduce it with exactly that code? – xaxxon May 13 '16 at 07:07
  • @xaxxon I don't remember messing with my toolchain and I can reproduce this exact error with this code. – Peter Lenkefi May 13 '16 at 07:23
  • @kakkoko Maybe that's a different version of the compiler which may not be in Visual Studio yet (But I'm just guessing) – Peter Lenkefi May 13 '16 at 07:50
  • @kakkoko http://rextester.com/LGS80945 repro -- and it's only the default constructor that is causing trouble: http://rextester.com/ZBQC93586 – xaxxon May 13 '16 at 08:20
  • It's a compiler bug that appears to have been fixed. Nothing more. – T.C. May 13 '16 at 08:30
  • @T.C. And where's that fix? – Peter Lenkefi May 13 '16 at 08:46
  • The future Update 3, I suppose, since your sample code works on http://webcompiler.cloudapp.net/. – T.C. May 13 '16 at 08:51
  • @T.C. Alright, guess have to wait then – Peter Lenkefi May 13 '16 at 09:33

1 Answers1

2
 template <typename... T>
    S(T&&... params)
    {
    }

T can be empty leaving you with a default constructor, it can be S&& leaving you with a move constructor, or it can be const S & leaving you with a copy constructor.

But you just told the compiler you want the default version of those, so it's confused because you just gave it an explicit definition for each of those as well.

I would propose the following as a solution, since it's only the default constructor that is causing the problem, but this code crashes the compiler:

struct S
{
    S() = default;
    S(S const&) = default;
    S(S&&) = default;

    S& operator=(S const& other) = default;
    S& operator=(S&&) = default;

    template <typename S, typename... T>
    S(S&& s, T&&... params)
    {
    }
};

int main()
{
    S s;
    return 0;
}
xaxxon
  • 19,189
  • 5
  • 50
  • 80