在施工期间是否有简洁的方法来获得会员的类型?

时间:2013-05-22 05:26:21

标签: c++ c++11 constructor decltype type-deduction

我有:

  • 模板例程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 个答案:

答案 0 :(得分:4)

  

在这里使用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);

如果你仍然考虑构造函数初始化列表verbose提供一个调用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))

并不是那么冗长,而且恰恰表达了意图。

答案 1 :(得分:1)

这有点像hackish,但如何使用模板化转换运算符为归档引入包装类:

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))
{}