I generally avoid inheritance, but it is (sadly) the only ABI-safe and portable solution (AFAIK) to optimise away empty members.
But doesn't work for final classes, or ones with protected constructors. But why would the protected constructor be an issue?
If you're using inheritance instead of using a data member, because you want the empty base optimization, then a protected constructor would not have been usable anyway. So why do you care about this case? If the type is awkward and unusable and breaks code that tries to use it, that's the type's problem. The user who tries to instantiate your class template with an unusable type can deal with it.
[[no_unique_address]] is not supported by Clang for windows, MSVC only allows the MSVC-prefixed version.
What an absolute s***show that has turned out to be :-(
But maybe I should tackle that instead...
On Sat, Oct 12, 2024 at 3:27 PM Jonathan Wakely <
cxx@kayari.org> wrote:
Hi!
I can't seem to find any information about how constraints and class access specifiers could work together. Currently it seems like concepts are always evaluated from "outside" a class (i.e. only public fields and methods affect the evaluation of the constraint).
Correct. That's essential to be able to cache the result, you don't want foo<T> to mean different things depending on where the first check happens, and you don't want the result to not be memoized (for performance during compilation).
E.g. for example:
```c++
#include <concepts>
#include <utility>
class clazz_with_protected_ctor {
protected:
explicit clazz_with_protected_ctor(int) {}
};
template <typename T>
struct clazz_wrapper: private T {
template <typename... Ts>
requires(std::constructible_from<T, Ts&&...>) explicit clazz_wrapper(Ts&&... args) : T(std::forward<T>(args)...) {}
};
void foo() {
// Generates compile-error since the constraint for the constructor can't see the protected constructor
auto my_wrapper = clazz_wrapper<clazz_with_protected_ctor>(1);
}
```
I wonder if not the above code should actually be a sensible piece of code (especially with CRTP-based API:s), and it may be needed that constraints are evaluated from the context that they are used.
Inheritance is an incredibly strong coupling, the strongest in C++. It doesn't really make sense to be inheriting from types where you don't know whether you can use a protected (or private, via friendship) API. Either inherit from arbitrary types provided as template args and rely on the members you need being public
I should have said "being accessible" rather than necessarily public. It's fine if the member you need to use is protected, because the derived class will be able to use it. It doesn't make sense to query whether it's usable though. If you're inheriting,the member you need to use need to be accessible
N.B. In the example above, you could just do `using T::T;` to get the desired effects. So you don't need to test for the constructor being usable.
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals