2

我有:

  • unarchive接受字典和键并基于传递的模板类型 ( )的模板例程T可以专门用于生成T
  • a 的构造函数,用于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))
{ }

如何才能做到这一点?

4

2 回答 2

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_mstatic_assert可以添加A以确保 of 的类型与担心通过不更改来更改类型的类型value_m相同:value_typevalue_mvalue_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))

不是那么冗长,而是准确地说明了意图。

于 2013-05-22T07:42:41.477 回答
1

这有点骇人听闻,但是如何使用模板转换运算符为存档引入包装类:

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))
{}
于 2013-05-22T08:29:45.730 回答