I made a static function of some class, and made constructor private. Now I want to use the function. Clang++ says "The constructor is private", while g++ compiles normally.
I don't know if there are any rules in any Standard which could affect this in any way. Any function can make a variable and there isn't and way it couldn't return a value. So there shouldn't be any errors with MyStruct::make
in the code above, right? But Clang feels differently about that.
Is this what Clang should make doable or is this that sort of thing that should never be done in C++?
I've tried to make C++ be a little more like Rust here, so that I could never do something unexpected with constructors. I used g++ and the following code works.
#include <iostream>
#include <optional>
#include <utility>
class MyStruct {
public:
static auto make(int val) -> MyStruct {
MyStruct that(val);
return that;
};
auto copy() -> MyStruct {
MyStruct copy(this->val);
return copy;
}
auto value() -> int { return this->val; }
private:
MyStruct() = delete;
MyStruct(int val) { this->val = val; }
MyStruct(const MyStruct &other) { this->val = other.val; }
int val;
};
auto main() -> int {
auto my_struct = MyStruct::make(4);
auto my_new_struct = my_struct.copy();
std::cout << my_new_struct.value();
std::cout << MyStruct::make(7).value();
}
With Clang, however, I've encountered some errors:
main.cpp:30:20: error: calling a private constructor of class 'MyStruct'
auto my_struct = MyStruct::make(4);
^
main.cpp:24:3: note: declared private here
MyStruct(const MyStruct &other) { this->val = other.val; }
^
main.cpp:32:24: error: calling a private constructor of class 'MyStruct'
auto my_new_struct = my_struct.copy();
^
main.cpp:24:3: note: declared private here
MyStruct(const MyStruct &other) { this->val = other.val; }
^
2 errors generated.
In other words, is this what Clang should make doable or is this that sort of thing that should never be done in C++, and why?
Formally for example in this line
auto my_struct = MyStruct::make(4);
there should be used the copy construtor if not take into account the copy/move elision.
Before the C++ 17 Standard the copy constructor shall be acceptable even if its call is elided.
From the C++ 14 Standard( 12.8 Copying and moving class objects)
- ... [Note: This two-stage overload resolution must be performed regardless of whether copy elision will occur. It determines the constructor to be called if elision is not performed, and the selected constructor must be accessible even if the call is elided. ā end note ]
Either make the copy constructor public or switch on the support of at least the C++ 17 Standard.