Info
-
Did you know that CRTP can be implemented with C++23
Deducing this
?
Example
template <class T>
struct interface {
auto get() const {
return static_cast<const T*>(this)->get_impl();
}
};
struct impl1 : interface<impl1> {
auto get_impl() const { return 1; }
};
struct impl2 : interface<impl2> {
auto get_impl() const { return 2; }
};
template<class T>
auto get(const interface<T>& b) {
return b.get();
}
int main() {
return get(impl1{}) + get(impl2{}); // returns 3
}
Puzzle
- Can you implement the CRTP example with
Deducing this
instead?
struct interface; // TODO
template<auto N> struct impl; // TODO
auto get(...); // TODO
static_assert(0 == get(impl<0>{}));
static_assert(1 == get(impl<1>{}));
static_assert(3 == get(impl<1>{}) + get(impl<2>{}));
Solutions
struct interface {
auto get(this const auto& impl) {
return impl.get_impl();
}
};
template<auto N> struct impl : interface {
auto get_impl() const { return N; }
};
auto get(const /*std::derived_from<interface>*/ auto& iface) {
return iface.get();
}
class interface {
public:
template<typename T>
[[nodiscard]] constexpr auto get(this const T&) {
return T::get_impl();
}
};
template<auto N>
class impl : interface {
private:
[[nodiscard]] static constexpr auto get_impl() {
return N;
}
};
[[nodiscard]] constexpr auto get(const auto &object) {
return object.get();
}
struct interface {
auto get(this const auto& impl) requires requires { impl.get_impl(); } {
return impl.get_impl();
}
};
template<class T> concept Interface = requires (T t) { t.get(); };
template<auto N> struct impl : interface {
auto get_impl() const { return N; }
};
auto get(const Interface auto& i) {
return i.get();
}
struct interface {
constexpr auto get(this const auto& self) {
return decltype(self)::value;
}
};
template<auto N> struct impl : interface {
static constexpr auto value = N;
};
auto get(const auto& i) {
return i.get();
}
struct interface
{
template <typename Self>
auto get(this Self && self)
{
return std::forward<Self>(self).get_impl();
}
};
template<auto N>
struct impl : interface
{
auto get_impl() const
{
return N;
}
};
template <typename T>
auto get(T && val) {
return std::forward<T>(val).get();
}
struct interface{
auto get( this auto && self )
{
return self();
}
};
template<auto N> struct impl:public interface {
auto operator()()
{
return N;
}
};
auto get(auto && f){
return f.get();
}
struct interface {
auto get(this auto const &self) {
return self.get_impl();
}
};
template<auto N> struct impl : interface {
auto get_impl() const { return N; }
};
auto get(const auto &self) { return self.get(); }
struct interface {
auto get(this auto const &self) {
return self.get_impl();
}
};
template<auto N> struct impl : interface {
auto get_impl() const { return N; }
};
auto get(const auto &self) { return self.get(); }