Sorry for the generic title, but it's a mindfu*k situation, which I can't easily describe.
Suppose the following code:
struct S
{
S() = default;
int x;
int y;
};
S f()
{
return { 1, 2 };
}
This compiles and works perfectly fine. I want to forbid it, as it's bug prone (the actual code is far more complex). So, I tried adding
template<typename T>
S(std::initializer_list<T>) = delete;
but guess what - nothing changes. Tested on Visual Studio 2019 with std=c++17. The C++ resharper shows this as an error, but msvc actually compiles this and it works.
Wait, now it gets interesting. If S() = default;
is replaced with S() {}
, the compilation fails with
'S::S<int>(std::initializer_list<int>)': attempting to reference a deleted function
OK, this looks like something to do with user-defined constructors and initialization?! Messy, but kinda understandable.
But wait - it gets even more interesting - keeping the = default
constructor, but making the fields private
also alters this behavior and guess what - the error has nothing to do with inaccessible members, but it again shows the error from above!
So, in order to make this deletion work, I should either make the fields private or define my own empty constructor (ignore the uninitialized x and y fields, this is just a simplified example), meaning:
struct S
{
S() = default;
// S() {}
template<typename T>
S(std::initializer_list<T>) = delete;
private:
int x;
int y;
};
clang 13 and GCC 11 behave exactly the same way, while GCC 9.3 fails to compile the original code (with =default
constructor, public fields, but deleted initializer list constructor).
Any ideas what happens?
Aucun commentaire:
Enregistrer un commentaire