7

我有以下模板方法:

struct MyStruct
{
  // ...
  template<typename T>
  void readField(std::istream& in, T& data)
  {
      read(in, data);
      data = ntohl(data);
  }
};

template<>
void MyStruct::readField<uint8_t>(std::istream& in, uint8_t& data)
{
    read(in, data);
}

但我得到了那些奇怪的链接器错误:

/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/exception:62: `void MyStruct::readField 的多重定义(std::basic_istream >&, unsigned char&)' ../Lib/obj/MyStruct.o:/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../。 ./include/c++/4.4.7/exception:62: 首先在这里定义 collect2: ld 返回 1 退出状态 make: *** [Lib] Error 1

我怎样才能专门化这个成员函数?

编辑

这种方法有效:

struct MyStruct
{
  // ...
  template<typename T>
  void readField(std::istream& in, T& data)
  {
    read(in, data);
    data = ntohl(data);
  }

  void readField(std::istream& in, uint8_t& data)
  {
    read(in, data);
  } 
};

或使用inlines 或在课堂外使用inline

struct MyStruct
{
  // ...
  template<typename T>
  void readField(std::istream& in, T& data)
  {
      read(in, data);
      data = ntohl(data);
  }
};

template<>
inline void MyStruct::readField<uint8_t>(std::istream& in, uint8_t& data)
{
    read(in, data);
}
4

2 回答 2

10

正如 Igor 提到的,您可以在头文件中实现泛型版本,然后在 cpp 文件中实现特化,例如:

// MyStruct.h

struct MyStruct {
  // ...
  template <typename T>
  void readField(std::istream& in, T& data) {
    read(in, data);
    data = ntohl(data);
  }
};

然后在 cpp 文件中你可以实现特化,例如:

// MyStruct.cpp

template <>
void MyStruct::readField<uint8_t>(std::istream& in, uint8_t& data) {
  read(in, data);
}

更新:阅读评论后,特化也可以在与主模板相同的头文件中,但不在结构中,例如(我通过编译和运行类似的示例验证了这一点,没有错误):

// MyStruct.h

struct MyStruct {
  // ...
  template <typename T>
  void readField(std::istream& in, T& data) {
    read(in, data);
    data = ntohl(data);
  }
};  

template <>
inline void MyStruct::readField<uint8_t>(std::istream& in, uint8_t& data) {
  read(in, data);
}

// End MyStruct.h
于 2016-01-26T15:43:45.397 回答
3

您可以inline专门化以避免多个定义。

template<>
inline void MyStruct::readField<uint8_t>(std::istream& in, uint8_t& data)
{
    read(in, data);
}

为了完整起见,您拥有的另一个选项是在 .cpp 文件中创建一个实现,并通过标题导出该实现。

//MyStruct.h

#ifdef MYSTRUCT_EXPORTS
#ifdef __GNUC__
#ifndef __linux__
#define MYSTRUCT_API __attribute__ ((dllexport))
#else
#define MYSTRUCT_API __attribute__ ((visibility ("default")))
#endif
#else
#define MYSTRUCT_API __declspec(dllexport)
#endif
#else
#ifdef __GNUC__
#ifndef __linux__
#define MYSTRUCT_API __attribute__ ((dllimport))
#else
#define MYSTRUCT_API __attribute__ ((visibility ("default")))
#endif
#else
#define MYSTRUCT_API __declspec(dllimport)
#endif
#endif

template<>
void MYSTRUCT_API MyStruct::readField<uint8_t>(std::istream& in, uint8_t& data);


//MyStruct.cpp

template<>
void MyStruct::readField<uint8_t>(std::istream& in, uint8_t& data)
{
    read(in, data);
}
于 2016-01-26T15:42:47.357 回答