【问题标题】:Set private attribute depending on template's typename根据模板的类型名设置私有属性
【发布时间】:2015-05-12 19:41:48
【问题描述】:

背景:
我们正在尝试设置一个名为 Operand 的类模板,它可以采用多种类型作为其类型名T。这些在以下枚举中定义:

enum eOperandType {
    INT8
    INT16,
    INT32,
    FLOAT,
    DOUBLE
};

那些对应<cstdint>中定义的类型,即int8_t, int16_t,以此类推。

构造函数必须Operand(std::string const & value);

template<class T>
class Operand : public IOperand
{

public:
    Operand(std::string const & value)
    {
        std::stringstream ss(value);

        ss >> _value;
        //_type = ??? ;
    }

[...]

private:
    Operand(void){}

    eOperandType    _type;
    T               _value;
};

接口 IOperand 在这里并不重要,只是一些用于运算符重载的原型。

问题:
设置_type 属性的最佳方法是什么?简单的方法是写几个if/else iftypeid 或类似的东西,但我觉得那样会很脏。此外,我只是认为在模板中使用typeid 只是意味着你在某处做错了......对吗?

【问题讨论】:

  • 为什么不将类型T 暴露为typedef?
  • 为什么不:template&lt;typename T&gt; class Operand: public IOPerand
  • @TamásSzabó 技术上不一样吗?参看。 stackoverflow.com/a/2024173/4891879

标签: c++ class templates


【解决方案1】:

使用辅助类推导出_type 的值。

template <typename T> struct OperandType;

template <> struct OperandType<int8_t>
{
    static const eOperandType t = INT8;
};

template <> struct OperandType<int16_t>
{
    static const eOperandType t = INT16;
};

等等

并将其用作:

Operand(std::string const & value) : type_(OperandType<T>::t)
{
   ...
}

附言

鉴于您可以随时推断出type_ 的值,将其存储为成员变量是否有意义?

【讨论】:

  • 回答您的 PS: IOperand 具有这些属性的吸气剂,我只是想我应该将它们存储在那里。对于实际的答案,我们认为它是这样的,但不确定这是一件好事。
  • @NathanaelC.,最好避免存储冗余数据。只有在需要消除性能瓶颈时才可以证明存储冗余是合理的。 YMMV。
  • 没想到,说得通:)谢谢!
【解决方案2】:

您可以使用模板重载。如果您为每种类型专门化模板参数,则可以设置特定参数,因为您可以在专门化模板中具有特定值。然后,您可以将该值用于_type 属性。所以如果你做这样的事情

template<typename _Ty> struct OperandSelector;

template<> struct OperandSelector<int8_t> {
    static const eOperandType value = INT8;
}

然后为您要使用的每个值创建另一个特化,在您的情况下为INT16INT32FLOATDOUBLE。要设置_type 的值,您可以像这样将OperandSelector&lt;T&gt;::value 的值分配给它

_type = OperandSelector<T>::value;

这种方法允许在编译时进行选择,并使选择值成为一个简单的副本。

【讨论】:

    【解决方案3】:
    template<class...>struct types{using type=types;};
    
    template<class E, E...es>
    using enums=std::integer_sequence<E,es...>;
    
    template<class types, class T, class enums>
    struct pick;
    
    template<class T0, class...Ts, class T, class E, E e0, E...es>
    struct pick< types<T0, Ts...>, T, enums<E,e0,es...>>:
      pick< types<Ts...>, T, enums<E,es...>>
    {};
    
    template<class T0, class...Ts, class E, E e0, E...es>
    struct pick< types<T0, Ts...>, T0, enums<E,e0,es...>>:
      std::integral_constant<E,e0>
    {};
    

    然后

    using c_types = types<int8_t, int16_t, int32_t, float, double>;
    using e_types = enums<eOperandType, INT8, INT16, INT32, FLOAT, DOUBLE>;
    

    在类本身:

    static const eOperandType _type = pick<c_types, T, e_types>::value;
    

    这不适用于数百种类型。

    这里我做了static const,因为它不能变化,所以为什么要让它呢?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-21
      • 1970-01-01
      • 2018-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多