c++ - 如何正确设计和实现函数模板特化?

标签 c++ c++11 template-specialization sfinae typetraits

我想从 std::ifstream 中实现一些读取函数。 它需要区分 Pod 类型和其他类型。 (当前 std::string)

template <typename T, typename = std::enable_if<std::is_pod<T>::value>::type>
T read(std::ifstream& fin);

template <>
std::string read<std::string, void>(std::ifstream& fin);

int main()
{
    std::ifstream fin("test", std::ios::binary);
    int x = read<int>(fin);
    std::string str = read<std::string, void>(fin);
}

当我为 std::string 调用读取时,我想从模板参数中删除“void”。 我怎样才能得到它?

提前致谢。


更新(2017/09/14)

我从 EC++ 得到提示并尝试实现以下代码。

    template <bool B>
    struct is_fundamental {
        enum { value = B };
    };

    template <typename T>
    static T doRead(std::ifstream& fin, is_fundamental<true>);

    template <typename T>
    static T doRead(std::ifstream& fin, is_fundamental<false>);

    template <>
    static std::string doRead<std::string>(std::ifstream& fin, is_fundamental<false>);

    template <typename T>
    static T read(std::ifstream& fin) {
        return doRead<T>(fin, is_fundamental<std::is_fundamental<T>::value>());
    }


    int main()
    {
        std::string filename("./test.dat");
        std::ifstream fin(filename, std::ios::binary);

        read<int>(fin);
        read<std::string>(fin);
        read<std::vector<int>>(fin);

        return 0;
    }

为每个读取调用<>都会获得正确的功能!

最佳答案

问题是不可能部分特化一个函数。

关于结构体的使用呢?

如果你写read广告跟随,

template <typename T>
struct read 
 {
   template <typename U = T>
   typename std::enable_if<std::is_same<U, T>::value 
                        && std::is_pod<T>::value, T>::type
      operator() (std::ifstream & fin)
    { /* do something; return a T */ }
 };

template <>
struct read<std::string>
 {
   std::string operator() (std::ifstream & fin)
    { /* do something; return a string */ }
 };

你有一个通用版本的 read结构,其中 operator()仅启用模板类型是 POD ,以及 std::string 的专用版本(并且您可以添加 read 的其他特化;也可以是部分特化)。

缺点是你必须改变read()的调用这样

int x = read<int>{}(fin);
std::string str = read<std::string>{}(fin);

也就是说,定义一个对象(read<T>{})。

如果您更喜欢在读取中使用静态成员——例如,func() -- 您可以避免创建对象的需要,但您必须以这种方式调用它

int x = read<int>::func(fin);
std::string str = read<std::string>::func(fin);

下面是一个完整的工作示例

#include <vector>
#include <fstream>
#include <iostream>
#include <type_traits>

template <typename T>
struct read 
 {
   template <typename U = T>
   typename std::enable_if<std::is_same<U, T>::value 
                        && std::is_pod<T>::value, T>::type
      operator() (std::ifstream & fin)
    { T ret ; std::cout << "POD!" << std::endl ; fin >> ret ; return ret; }
 };

template <>
struct read<std::string>
 {
   std::string operator() (std::ifstream & fin)
    { std::string ret ; std::cout << "string!" << std::endl; fin >> ret ;
      return ret; }
 };

int main()
 {
   std::ifstream fin("test", std::ios::binary);
   int x = read<int>{}(fin);                    // write POD!
   std::string str = read<std::string>{}(fin);  // write string!
   //auto read<std::vector<int>>{}(fin);        // compilation error
 }

关于c++ - 如何正确设计和实现函数模板特化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46147046/

相关文章:

php - 客户端/服务器通信的最佳协议(protocol),从 PHP/Perl 到 C++/Qt4

C++ 模板 - 几个特化 - 是否定义了行为?

c++ - 如何从迭代器获取迭代器底层类型?

c++ - 具有模板化参数的模板函数特化

c++ - 可变参数模板的模板特化

c++ - 简化大量模板特化

c++ - 使用 pthread 唤醒多线程的最佳方法

c++ - 执行 constexpr 运算符重载的指南?

c++ - 通过单个函数返回另一个函数的多个参数

c++ - 需要了解函数模板解析规则