Метапреграммирование шаблона C ++ - Выбор диапазона аргументов из пакета параметровC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Метапреграммирование шаблона C ++ - Выбор диапазона аргументов из пакета параметров

Сообщение Anonymous »

Я делаю систему ECS с компиляцией и создал класс архетипа для хранения компонентов: < /p>

Код: Выделить всё

template
class Archetype;

template
struct ComponentStorage {
T* data = nullptr;

Deep_Inline T* Get() const;
};

template
class Archetype : private ComponentStorage... {
// ...
}
< /code>
Я хочу позволить ему принимать компоненты, которые не имеют тривиальных конструкторов, но это означает, что при создании сущности мне нужно иметь возможность передавать аргументы каждому требуемому конструктору компонентов.archetype.CreateEntity(std::in_place_type, arg1, arg2, std::in_place_type, arg3, arg4);
So component A is constructed being passed arg1, arg2 and B is constructed with arg3, arg4 etc...
Ideally order doesn't matter as it uses the tags std::in_place_type
I have a working system to extract the needed arguments using std :: tuple :

Код: Выделить всё

#include 
#include 
#include 
#include 

// Helpers to detect if a type is std::in_place_type
template
struct is_in_place_type : std::false_type {};
template
struct is_in_place_type : std::true_type {};

// Implementation for iterating over arguments to find std::in_place_type tag and collect arguments
template
struct GetComponentArgsImpl;

// Specialization when no arguments are left, returns empty tuple
template
struct GetComponentArgsImpl {
static auto Get() {
return std::tuple();
}
};

// Specialization that collects all arguments belonging to std::in_place_type_t
// Returns a std::tuple containing said arguments
template
struct GetComponentArgsImpl {
private:
// Collect all arguments until next std::in_place_type
template
struct Collector {
template
static auto Collect(std::tuple in_collected, First&& in_first, Others&&... in_others) {
if constexpr (is_in_place_type::value) {
// Next in_place_type found, stop collecting
return in_collected;
} else {
// Collect this arg and recurse
return Collector::Collect(
std::tuple_cat(in_collected, std::forward_as_tuple(std::forward(in_first))),
std::forward(in_others)...);
}
}

// No more args
static auto Collect(std::tuple in_collected) {
return in_collected;
}
};

public:
static auto Get(const std::in_place_type_t&, Rest&&... in_rest) {
return Collector::Collect(std::tuple(), std::forward(in_rest)...);
}
};

// Specialization when encountering a std::in_place_type argument
// Skips until std::in_place_type matches type T
template
struct GetComponentArgsImpl {
private:
// Skip the args belonging to U until next std::in_place_type
template
struct Skipper {
template
static auto Skip(First&& in_first, Others&&...  in_others) {
if constexpr (is_in_place_type::value
&& std::is_same_v) {
// Next tag found, recurse on get_inplace_args_impl
return GetComponentArgsImpl::Get(in_first, std::forward(in_others)...);
} else {
// Skip this arg and continue skipping
return Skipper::Skip(std::forward(in_others)...);
}
}
// No more args while skipping means T not found
static auto Skip() {
return std::tuple();
}
};

public:
static auto Get(const std::in_place_type_t&, Rest&&... in_rest) {
return Skipper::Skip(std::forward(in_rest)...);
}
};

// Unpacks an std::in_place_type argument list from parameters:
// GetComponentArgs(std::in_place_type, 1, 2, std::in_place_type, 3, 4, std::in_place_type, 5, 6);
// -> std::tuple(3, 4);
template
auto GetComponentArgs(TaggedArgs&&... in_args) {
return GetComponentArgsImpl::Get(std::forward(in_args)...);
}

struct A {};
struct B {};
struct C {};

int main() {
auto extractedArgs = GetComponentArgs(std::in_place_type, 1, 2, std::in_place_type, 3, 4, std::in_place_type, 5, 6);
std::cout   Я также должен добавить, что я использую в первую очередь MSVC. Я только что заметил, что выход GCC сильно отличается от MSVC One. В идеале это работает на обоих!> 

Подробнее здесь: [url]https://stackoverflow.com/questions/79684048/c-template-metaprogramming-selecting-a-range-of-arguments-from-a-parameter-p[/url]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»