根据模板的typename设置private属性

时间:2015-05-12 19:41:49

标签: c++ class templates

上下文
我们正在尝试设置一个名为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 if写一些typeid或接近它的东西,但我觉得那会很脏。此外,我只是认为在模板中使用typeid只是意味着你在某处做错了什么......对吗?

3 个答案:

答案 0 :(得分:5)

使用帮助程序类推导出_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)
{
   ...
}

<强> PS

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

答案 1 :(得分:4)

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

template<typename _Ty> struct OperandSelector;

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

然后为您要使用的每个值创建另一个专门化,例如INT16INT32FLOATDOUBLE。要设置_type的值,您可以使用OperandSelector<T>::value这样的值为其分配

_type = OperandSelector<T>::value;

这种方法允许在编译时完成选择,并选择值作为简单副本。

答案 2 :(得分:0)

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,因为它不能改变,为什么要这样呢?