Я имею:
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))
{ }
Как это может быть сделано?
Преимущество использования 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))
это не так многословно и точно заявляет намерение.
Это немного странно, но как насчет введения класса-обертки для архива с оператором преобразования по шаблонам:
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))
{}