如何专门化模板成员功能?

时间:2016-01-26 15:21:12

标签: c++ templates member-functions template-function

我有以下模板方法:

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 /../../../../包括/ C ++ / 4.4.7 /异常:62:   `void MyStruct :: readField的多重定义(std :: basic_istream&gt;&amp;,unsigned   炭&安培)”   ../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]错误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);
  } 
};

或使用inline s或使用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);
}

2 个答案:

答案 0 :(得分:4)

正如Igor所说,你可以在头文件中实现通用版本,然后在cpp文件中实现专门化,例如:

Declare @mytable Table 
(ID int , Name char (10),Petowner char (10), Pettype char (10), CreateDate Date)

Insert into @mytable
Values (1,'Steve','Peter', 'Dog', ('18951024','yyyymmdd'),
       (2,'Sid',  'Marin', 'Fish',('18951024','yyyymmdd'),
       (3,'Stan', 'Nick',  'Cat', ('1895102','yyyymmdd')

Select ID as 'ID', Name as 'Pet name',Petowner as 'Owners name',
     Pettype as 'Pet type', CreateDate as 'Date'  
From @mytable

然后在cpp文件中,您可以实现专门化,例如:

// MyStruct.h

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

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

// MyStruct.cpp

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

答案 1 :(得分:2)

您可以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);
}