Здравствуйте, koenjihyakkei, Вы писали:
K>Здравствуйте, _NN_, Вы писали:
_NN>>В C++17 не будет ни копирования не перемещения, а будет отложенная материализация:
K>Ну вроде и так С++17, а ваш код с запрещенным копи конструктором не компилируется: https://gcc.godbolt.org/z/owCH7y
Можно перенести тело вспомогательных функций в сам класс и тогда всё собирается:
#include <type_traits>
#include <utility>
#include <tuple>
template<typename... Types>
decltype(auto) get_last_tuple_element(std::tuple<Types...> tp)
{
return (std::get<std::tuple_size_v<std::tuple<Types...>> -1>(tp));
}
struct A
{
A() {}
A(int, int, int) {}
A(A const&) = delete;
A(A&&) = delete;
};
template<typename T>
struct B : public T
{
template<typename... Args>
B(Args&&... args) :
B(std::forward_as_tuple(args...), std::make_index_sequence<sizeof...(Args) - 1>{}, get_last_tuple_element(std::tie(args...)) )
{
}
int _v;
private:
template<typename... Args, std::size_t... Is>
B(std::tuple<Args...> tp, std::index_sequence<Is...>, int v) : T(std::get<Is>(tp)...), _v(v)
{
}
};
int main()
{
B<A> b1(1);
B<A> b(1, 2, 3, 4);
}
Здравствуйте, _NN_, Вы писали:
Это уже интереснее, мысль понятна, спасибо. Если обернуть еще макросами, то можно сократить количество вспомагательного кода, тогда менее верятно, что меня с этим пошлют
А то эти struct B не только я буду писать.
Здравствуйте, koenjihyakkei, Вы писали:
K>Здравствуйте, _NN_, Вы писали:
K>Это уже интереснее, мысль понятна, спасибо. Если обернуть еще макросами, то можно сократить количество вспомагательного кода, тогда менее верятно, что меня с этим пошлют А то эти struct B не только я буду писать.
Полагаю можно поиграться с кодом и упростить, может с CRTP или другим подходом.
Всё же, если не критично ставить параметры класса вначале, а не в конце, то это будет лучшим решением.
Здравствуйте, koenjihyakkei, Вы писали:
Если кому интересно, поигрался с версией от _NN_ и пришел к следующему варианту. Буду благодарен если кто подскажет, как можно улучшить.
Единственно у него есть один недостаток и возможно достаточно серьезный: не работает implicit conversion — компиляция падает с ошибкой "recursive template instantiation exceeded maximum depth", что в принципе логично.
То есть если конструктор ждет unsigned, а передается 123, а не 123u, то ошибка.
Причем если не менять параметр template-depth (по умолчанию он 1024) то компиляция может занимать приличное время. В общем неприятная ситуация получается.
http://coliru.stacked-crooked.com/a/facf23243c3cdbeb
#include <type_traits>
#include <utility>
#include <tuple>
#include <iostream>
#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define MIXIN_INIT() T(std::get<Is>(tp)...)
#define MIXIN_CONSTRUCTOR(MIXIN, ...) \
static constexpr size_t ArgsNum = VA_NARGS(__VA_ARGS__); \
template<typename... Args> \
MIXIN(Args&&... args) : MIXIN(std::forward_as_tuple(args...), std::make_index_sequence<ArgsNum>{} ) {} \
\
template<typename... Args, std::size_t... Is> \
MIXIN(std::tuple<Args...> tp, std::index_sequence<Is...>) : \
MIXIN(tp, std::make_index_sequence<sizeof...(Args) - ArgsNum>{}, std::get<sizeof...(Args) - ArgsNum + Is>(tp)... ) {} \
\
template<typename... Args, std::size_t... Is> \
MIXIN(std::tuple<Args...> tp, std::index_sequence<Is...>, __VA_ARGS__)
template<typename... Args>
void print(Args... args) {
((std::cout << ' ' << args), ...) << std::endl;
}
struct Base
{
Base(int v1, const char* v2) : a(v1), b(v2) {}
Base(Base const&) = delete;
Base(Base&&) = delete;
int a;
const char* b;
};
template<typename T>
struct Foo : public T
{
MIXIN_CONSTRUCTOR(Foo, bool v, float v2) : MIXIN_INIT(), c(v), d(v2) {}
bool c;
float d;
};
template<typename T>
struct Bar : public T
{
MIXIN_CONSTRUCTOR(Bar, char c, float f, uint32_t n) : MIXIN_INIT(), ch(c), fl(f), num(n) {}
char ch;
float fl;
uint32_t num;
};
struct Final : public Bar<Foo<Base>> {
using Base = Bar<Foo<Base>>;
using Base::Base;
};
int main()
{
Foo<Base> f1(1, "hello", true, 1.0f);
print(f1.a, f1.b, f1.c, f1.d);
Bar<Base> f(1, "hello", 'a', 3.14f, 123u);
print(f.a, f.b, f.ch, f.fl, f.num);
Final f2(1, "hello", true, 1.24f, 'r', 3.14f, 123u);
print(f2.a, f2.b, f2.c, f2.d, f2.ch, f2.fl, f2.num);
}
Здравствуйте, koenjihyakkei, Вы писали:
K>Здравствуйте, koenjihyakkei, Вы писали:
K>Если кому интересно, поигрался с версией от _NN_ и пришел к следующему варианту. Буду благодарен если кто подскажет, как можно улучшить.
K>Единственно у него есть один недостаток и возможно достаточно серьезный: не работает implicit conversion — компиляция падает с ошибкой "recursive template instantiation exceeded maximum depth", что в принципе логично.
K>То есть если конструктор ждет unsigned, а передается 123, а не 123u, то ошибка.
K>Причем если не менять параметр template-depth (по умолчанию он 1024) то компиляция может занимать приличное время. В общем неприятная ситуация получается.
Что-то сложно получилось.
Да ещё и макрос думаю упростить можно.
Кстати, нужно использовать Args&&... , чтобы избежать копирования
template<typename... Args>
void print(Args&&... args) {
((std::cout << ' ' << args), ...) << std::endl;
}
P.S.
https://www.walletfox.com/course/cheatsheets_cpp.php