My code needs a special constructor that std::construct_at can use. This works fine if it's public but then it can be accessed by users of the class. If it is private, std::construct_at fails. Here's the minimal code:
#include <memory>
#include <iostream>
class Vec {
public:
int* const p{};
const int len{};
Vec(int len = 1) : len(len), p(new int[len]{}) {}
// Raw ctor, for use only inside class using std::construct_at to overlay object
// Doesn't work executed from std::construct_at if private
Vec(int* p, int len) : p(p), len(len) {}
Vec& operator=(Vec&& rhs)
{
delete[] p;
std::construct_at(this, rhs.p, rhs.len); // dtor not needed for this class
std::construct_at(&rhs, nullptr, 0); // steal rhs guts and make valid
return *this;
}
// .... Other ctors
~Vec() {delete[] p;}
};
int main()
{
int* pi{};
Vec x(pi, 0); // ctor accessable to users. Not good.
Vec a, b(2);
b.p[1] = 42;
a = std::move(b);
std::cout << "a.p[1] " << a.p[1] << " b.p (Null) " << b.p << "\n";
}
So I tried creating an empty struct tag (INNER) defined in the private space, but used in the public ctor. This works:
#include <memory>
#include <iostream>
class Vec {
struct INNER {};
public:
int* const p{};
const int len{};
Vec(int len = 1) : len(len), p(new int[len] {}) {}
// Raw ctor, for use only inside class using std::construct_at to overlay object
// Doesn't work executed from std::construct_at if private
Vec(int* p, int len, struct INNER) : p(p), len(len) {}
Vec& operator=(Vec&& rhs)
{
delete[] p;
std::construct_at(this, rhs.p, rhs.len, INNER{}); // dtor not needed for this class
std::construct_at(&rhs, nullptr, 0, INNER{}); // steal rhs guts and make valid
return *this;
}
// .... Other ctors
~Vec() { delete[] p; }
};
int main()
{
int* pi{};
//Vec x(pi, 0, Vec::INNER{}); // not compilable since INNER is private
Vec a, b(2);
b.p[1] = 42;
a = std::move(b);
std::cout << "a.p[1] " << a.p[1] << " b.p (Null) " << b.p << "\n";
}
While this works in GCC, CLANG, and MSVC. But it seems odd that std::construct_at can use it since INNER is defined in the private segment. Is std::construct_ats use of INNER legit?