如何专门针对多种类型的模板类的非模板成员函数?

时间:2018-08-26 13:54:33

标签: c++ template-specialization

我对要部分专用于多种类型的成员函数所需的语法感到不满。这是我所拥有的:

#include <cstdint>
#include <string>

class Property
{
public:
    virtual int read(uint8_t *) = 0;
};

template<typename T>
class PropertyValue
{
    T value_;
public:
    int read(uint8_t *);
};

// specialized for std::string
template<>
int PropertyValue<std::string>::read(uint8_t *buf) { /* put string-value to buf */}

现在,我想专门针对不同枚举类型的读取功能。我尝试了enable_ifis_same的组合,这些组合看起来令人反感,然后将其放入模板声明中(编译器告诉我现在有2个模板参数,而预期是1个)。

将其放入类定义中也不起作用。在外面...好,这就是我目前拥有的。

// specialize for some enums
template<typename T>
typename std::enable_if<std::is_same<T, enum Enum1>::value ||
                        std::is_same<T, enum Enum2>::value, int>::type
PropertyValue<T>::read(uint8_t *buf)
{
    return encode_enum(buf, value_);
}

我的想法哪里错了?

编辑:像这样编写并编译并起作用:

template<>
int PropertyValue<Enum 1>::read(uint8_t *buf)
{
    return encode_enum(buf, value_);
}

template<>
int PropertyValue<Enum 2>::read(uint8_t *buf)
{
    return encode_enum(buf, value_);
}

1 个答案:

答案 0 :(得分:3)

PropertyValue::value本身不是模板。它不是模板类,也不是模板函数。它是模板类的成员,与模板本身不同。

您必须专门研究整个课程。

template<>
class PropertyValue<std::string>
{
    std::string value_;
public:
    int read(uint8_t *)
    {
          // Your specialization goes here.
    }
};

即使read()本身是模板,也必须专门化其类,然后才能专门化模板类的模板成员。

当然,如果您的模板类具有许多其他成员和方法,则每个成员和方法都必须在此处进行专门化,从而导致大量代码被重复。届时,您将面临几种重构重复代码的选择。最好的方法取决于特定的细节。

但这就是完成的方式...

编辑:一种常见的方法是使用帮助程序模板类:

template<typename T> class PropertyValue; // Forward declaration

template<typename T> class do_read {
public:

    static int do_it( PropertyValue<T> &me, uint8_t *p )
    {
        // your default implementation
    }
};

template<> class do_read<std::string> {
public:

    static int do_it( PropertyValue<std::string> &me, uint8_t *p )
    {
        // your specialization
    }
};


template<typename T>
class PropertyValue
{
    T value_;
public:
    int read(uint8_t *p)
    {
          return do_read<T>::do_it(*this, p);
    }
};