根据模板的类型名称设置私有属性

Set private attribute depending on template's typename

本文关键字:设置 属性 类型      更新时间:2023-10-16

上下文:
我们正在尝试设置一个名为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属性的最佳方法是什么?简单的方法是只用typeid写几个if/else if或与之接近的东西,但我觉得那很脏。此外,我只是认为在模板内使用typeid只是意味着您在某个地方做错了...

使用助手类推断_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_的值,将其存储为会员变量是有意义的吗?

您可以使用模板过载。如果您为每种类型的模板参数进行专门设计,则可以为您设置一个特定参数,以便在专用模板中具有特定值。然后,您可以将该值用于_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;

这种方法将允许在编译时进行选择,并使选择值简单副本。

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;

这与许多100型类型都无法使用。

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