c++ 用于有条件地添加成员的CRTP

jfewjypa  于 2023-03-25  发布在  其他
关注(0)|答案(1)|浏览(122)

有没有可能写一个CRTP类,在一个类中添加一个成员,只有当一个同名的成员不存在时(在C++17中)?

template<class C> using require_foo = ...;

struct Foolish : require_foo<Foolish> {
    int foo;
}; // contains just one foo, CRTP is an empty base

struct NotFoolish : require_foo<NotFoolish> {
}; // contains just one foo, provided by CRTP base

我试了显而易见的方法:

#include <type_traits>

void has_foo_helper(...);

template<class Class>
auto has_foo_helper(Class* obj) -> decltype(obj->foo);

template<class Class>
constexpr bool has_foo =
    std::is_same_v<decltype(has_foo_helper(std::declval<Class*>())), int>;

template<class, bool>
struct require_foo_impl;

template<class Class>
struct require_foo_impl<Class, false> {
};

template<class Class>
struct require_foo_impl<Class, true> {
    int foo;
};

template<class Class>
using require_foo = require_foo_impl<Class, has_foo<Class>>;

但它不起作用:

static_assert(has_foo<Foolish>); // failed due to requirement 'has_foo<Foolish>'
static_assert(has_foo<NotFoolish>); // failed due to requirement 'has_foo<NotFoolish>'

想想看,has_foo似乎是自相矛盾的:如果一个类没有foo,它会添加它,但是现在这个类有了foo,所以它不会添加它,等等。
所以我对解决方案的存在持悲观态度,但我希望被证明是错误的。

uoifb46i

uoifb46i1#

在C中没有解决方案,也不太可能有一个。
最根本的问题是FoolishNotFoolish的定义在它们的右括号之前是不完整的,并且它们需要从一个超类继承,而这个超类需要有一个从它继承的类的完整定义。没有一个完整的定义,就不可能通过CRTP、SFINAE或任何其他技术来确定。而超类必须有一个完整的定义,在任何继承自它的类的定义都是完整的之前。
鸡与蛋的问题在C
中根本无法解决。

相关问题