Нужны ли для этого метаклассы или достаточно рефлексии?
Так что я с нетерпением ждал появления метаклассов . Затем я услышал, что этого не будет в C ++23c ++23, поскольку они думают, что нам сначала нужно отражение и реификация в языке, прежде чем мы добавим метаклассы.
Просматривая отражение в , кажется, что есть возможности реификации. Достаточно ли их, чтобы решить, что будут делать метаклассы; т.е. являются ли метаклассы просто синтаксическим сахаром?
Используя текущее предложение , можем ли мы воспроизвести кого-нибудь, написавшего такой тип, как:
interface bob {
void eat_apple();
};
и генерируя такой тип:
struct bob {
virtual void eat_apple() = 0;
virtual ~bob() = default;
};
Чтобы пойти дальше, взяв что-то похожее на
vtable bob {
void eat_apple();
~bob();
};
poly_value bob_value:bob {};
и возможность генерировать
// This part is optional, but here we are adding
// a ADL helper outside the class.
template<class T>
void eat_apple(T* t) {
t->eat_apple();
}
struct bob_vtable {
// for each method in the prototype, make
// a function pointer that also takes a void ptr:
void(*method_eat_apple)(void*) = 0;
// no method_ to guarantee lack of name collision with
// a prototype method called destroy:
void(*destroy)(void*) = 0;
template<class T>
static constexpr bob_vtable create() {
return {
[](void* pbob) {
eat_apple( static_cast<T*>(pbob) );
},
[](void* pbob) {
delete static_cast<T*>(pbob);
}
};
}
template<class T>
static bob_vtable const* get() {
static constexpr auto vtable = create<T>();
return &vtable;
}
};
struct bob_value {
// these should probably be private
bob_vtable const* vtable = 0;
void* pvoid = 0;
// type erase create the object
template<class T> requires (!std::is_base_of_v< bob_value, std::decay_t<T> >)
bob_value( T&& t ):
vtable( bob_vtable::get<std::decay_t<T>>() ),
pvoid( static_cast<void*>(new std::decay_t<T>(std::forward<T>(t))) )
{}
~bob_value() {
if (vtable) vtable->destroy(pvoid);
}
// expose the prototype's signature, dispatch to manual vtable
// (do this for each method in the prototype)
void eat_apple() {
vtable->method_eat_apple(pvoid);
}
// the prototype doesn't have copy/move, so delete it
bob_value& operator=(bob_value const&)=delete;
bob_value(bob_value const&)=delete;
};
Живой пример , оба из которых являются примерами того, чем меня восхищали метаклассы.
Я меньше беспокоюсь о синтаксисе (возможность написать библиотеку и сделать создание поли-значений или интерфейсов просто полезным, точный синтаксис - нет) настолько, насколько я обеспокоен тем, что он способен на это.
1 ответ
Просматривая отражение в c ++23 , кажется, что есть возможности реификации. Достаточно ли их, чтобы решить, что будут делать метаклассы; т.е. являются ли метаклассы просто синтаксическим сахаром?
Называть это отражением в C++23 ... оптимистично. Но ответ - да. Цитата из P2237:
метаклассы - это просто синтаксический сахар поверх функций, описанных [ранее]
Как указывается в документе, синтаксис метакласса:
template<typename T, typename U>
struct(regular) pair{
T first;
U second;
};
означает просто:
namespace __hidden {
template<typename T, typename U>
struct pair {
T first;
U second;
};
}
template <typename T, typename U>
struct pair {
T first;
U second;
consteval {
regular(reflexpr(pair), reflexpr(__hidden::pair<T, U>));
}
};
где
regular
это некоторая функция, которая вводит кучу кода. Но для того, чтобы это вообще работало, нам нужно иметь языковые средства, поддерживающие
consteval
функция, которая вводит кучу кода. Метаклассы просто предоставляют приятный интерфейс, но это лишь часть того, что, надеюсь, мы сможем делать с помощью внедрения кода.