Есть ли краткий способ получить тип члена во время строительства?

Я имею:

  • Шаблонная рутина unarchive который берет словарь и ключ и основанный на типе шаблона (TПройденный может быть специализирован для производства T
  • Конструктор для struct что использует unarchive построить своих членов

Примером может быть следующее:

template <typename T>
T unarchive(const dictionary_t&, key_type key);

struct foo
{
foo(const dictionary& archive) :
value_m(unarchive<decltype(value_m)>(archive, value_key))
{ }

some_value_type value_m;
};

Преимущество использования unarchive<decltype(value_m)> вот что я могу изменить тип value_m без необходимости обновлять эту строку кода — тип всегда следует за типом переменной-члена.

У меня проблема более эстетическая: она очень многословна. В настоящее время у меня есть макрос:

#define UNARCHIVE_FOR(var) unarchive<decltype(var)>

И fooконструктор меняется следующим образом:

foo(const dictionary& archive) :
value_m(UNARCHIVE_FOR(value_m)(archive, value_key))
{ }

Теперь у меня есть более резкий, но гораздо более ужасный результат. Можно ли достичь того же результата без макроса? Что бы я хотел, было бы что-то похожее на:

foo(const dictionary& archive) :
value_m(unarchive<value_m>(archive, value_key))
{ }

Как это может быть сделано?

2

Решение

Преимущество использования unarchive заключается в том, что я могу изменить тип value_m без необходимости обновлять эту строку кода — тип всегда следует за типом переменной-члена.

Одна альтернатива — создать псевдоним для типа value_m и устранить decltype(value_m) из списка инициализатора конструктора:

struct foo
{
using value_type = int;

foo(const dictionary_t& archive, const key_type value_key) :
value_m(unarchive<value_type>(archive, value_key))
{ }

value_type value_m;
};

unarchive<value_type> все еще следует за типом value_m, static_assert могут быть добавлены для обеспечения типа value_m такой же как value_type если есть опасение об изменении типа value_m не меняя value_type:

static_assert(std::is_same<decltype(value_m), value_type>::value,
"'value_m' type differs from 'value_type'");

или установить псевдоним в зависимости от типа value_m:

int value_m;
using value_type = decltype(value_m);

Если вы по-прежнему рассматриваете список инициализации конструктора многословно, предоставьте static функция-обертка, которая вызывает unarchive() функция:

struct foo
{
using value_type = int;

foo(const dictionary_t& archive, const key_type value_key) :
value_m(unarchive_(archive, value_key))
{ }

static value_type unarchive_(const dictionary_t& d, key_type k)
{
return unarchive<value_type>(d, k);
}

value_type value_m;
};

Сказав все это:

value_m(unarchive<decltype(value_m)>(archive, value_key))

это не так многословно и точно заявляет намерение.

4

Другие решения

Это немного странно, но как насчет введения класса-обертки для архива с оператором преобразования по шаблонам:

class wrapper {
const dictionary_t& dict_m;
const key_type key_m;
public:
wrapper(const dictionary_t& d, key_type k) :
dict_m(d), key_m(k) {}
template <class T> operator T () const {
return unarchive<T>(dict_m, key_m);
}
};

так что вы можете инициализировать с помощью:

foo(const dictionary_t& archive, const key_type value_key) :
value_m(wrapper(archive, value_key))
{}
1

По вопросам рекламы [email protected]