Упаковка пакетов параметров - PullRequest
0 голосов
/ 06 сентября 2018

Недавно я столкнулся с проблемой, единственное решение которой я могу придумать, это использовать макросы, которые хотя и подходят для некоторых целей, но я считаю, что это уродливое решение.

Проблема заключается в объявлении класса, параметры шаблона которого постоянно изменяются по мере добавления кода и новых функциональных возможностей.

Я понимаю, что это может означать, что дизайн кода не будет выполнен хорошо, если количество шаблонов в классе постоянно меняется, но даже в этом случае я хотел бы знать, есть ли какое-либо решение.

Это пример кода в Test.hpp, объявление класса и прототипа всех его методов.

template<typename A,
         typename B,
         typename C>
struct Test 
{
    void do_something_1();
    void do_something_2();
    void do_something_3();
}

В Test.cpp мы реализовали бы все методы как таковые

template<typename A,
         typename B,
         typename C>
Test<A,B,C>::do_something_1() { /* ... */ }

template<typename A,
         typename B,
         typename C>
Test<A,B,C>::do_something_2() { /* ... */ }

template<typename A,
         typename B,
         typename C>
Test<A,B,C>::do_something_3() { /* ... */ }

Как вы можете видеть, мы часто повторяем шаблонную часть, и если бы мы добавили typename D класс, нам пришлось бы изменить его во всех методах Test.cpp, и так используя макросы, мы можем определить все это в макросе и использовать его, но тогда человек, читающий код, может не понять, что именно там происходит, или как макрос выглядит развернутым.

Можно также использовать typename... Args, чтобы получить их все, а затем каким-то образом обработать их внутри класса, но это очень неуклюже, поскольку получить N-й тип из Args не очень легко, и это не дает конца пользователь с указанием того, сколько типов должно использоваться и в каком порядке, кроме как внутри документации, и если мы хотим разделить параметры шаблона на две категории, скажем, один для каких типов хранить, а другой для каких типов преобразовывать в класс, который каким-то образом типы процессов, с двумя typename... Args нет простого способа сказать, где заканчивается первый и где начинается второй.

Единственный подход, который я мог придумать, - это добавить упакованную структуру, которая является структурой типов, и использовать ее как таковую:

In Test.hpp

template<typename A_,
         typename B_,
         typename C_>
struct packed_struct
{
    using A = A_;
    using B = B_;
    using C = C_;
};

template<typename packed_struct_type>
struct Test
{
    using A = typename packed_struct_type::A;
    using B = typename packed_struct_type::B;
    using C = typename packed_struct_type::C;

    void do_something_1();
    void do_something_2();
    void do_something_3();
};

И в Test.cpp мы бы просто объявили одно имя типа pack_struct_type, и мы могли бы также легко добавить параметр в любое время, это выглядит как лучшее решение, потому что тогда мы можем установить, сколько должно быть параметров шаблона и имя каждого, чтобы пользователь не мог их перепутать.

С предложением N3728 и предложением N1603 мы могли бы объявить typename... Args, пользователь мог бы создать его экземпляр с помощью Test< <int, char, double> >, и мы могли бы легче получать каждый тип, но они не были не одобрено.

Конечно, возможно, лучшим способом была бы поддержка языка первого класса для упакованных структур, которую мы могли бы использовать вместо typename для принудительного применения этого пакета, в основном то, что предложение N3728 делает с <int, char, double> синтаксис, но с использованием packed_struct Args вместо typename... Args, чтобы можно было легко извлекать каждый тип с его именем, вместо того, чтобы угадывать, какой тип является первым и вторым типом, и иметь возможность для пользователя также смешивать типы в своих декларация. Но я не могу найти никакого предложения относительно этой конкретной функциональности, и поэтому лучший способ, которым я могу придумать для достижения этого, - это решение pack_struct, которое я дал выше.

Есть ли лучшее решение для этой проблемы или любое предложение, которое дает решение, запланированное для c ++ 2a (или, возможно, позже, но еще не отклоненное)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...