代码之家  ›  专栏  ›  技术社区  ›  TC.

如何为具有特定类型特征的所有类型编写函数模板?

  •  7
  • TC.  · 技术社区  · 16 年前

    请考虑以下示例:

    struct Scanner
    {
        template <typename T>
        T get();
    };
    
    template <>
    string Scanner::get()
    {
        return string("string");
    }
    
    template <>
    int Scanner::get()
    {
        return 10;
    }
    
    int main()
    {
        Scanner scanner;
        string s = scanner.get<string>();
        int i = scanner.get<int>();
    }
    

    这个 Scanner 类用于从某个源提取标记。上面的代码很好用,但是当我试图 get 其他积分类型,如 char unsigned int .读取这些类型的代码与读取 int . 我可以为我想阅读的所有其他整型复制代码,但我宁愿为所有整型定义一个函数模板。

    我试过以下方法:

    struct Scanner
    {
        template <typename T>
        typename enable_if<boost::is_integral<T>, T>::type get();
    };
    

    这很有魅力,但我不确定如何获得 Scanner::get<string>() 再次运行。那么,我该如何编写代码才能做到 scanner.get<string>() scanner.get<any integral type>() 并且有一个单一的定义来读取所有的整型?

    更新:奖金问题 如果我想接受基于某些特性的多个类的范围呢?例如:如果我想要三个,我应该如何处理这个问题 得到 分别接受(i)整型(i i)浮点型(i i i)字符串的函数。

    2 回复  |  直到 16 年前
        1
  •  10
  •   Sergey Kurenkov    16 年前
    struct Scanner
    {
        template <typename T>
        typename boost::enable_if<boost::is_integral<T>, T>::type get()
        {
            return 10;
        }
        template <typename T>
        typename boost::disable_if<boost::is_integral<T>, std::string>::type get()
        {
            return "string";
        }
    };
    

    更新“如果我想接受基于某些特性的多个类范围怎么办?”

    struct Scanner
    {
        template <typename T>
        typename boost::enable_if<boost::is_integral<T>, T>::type get()
        {
            return 10;
        }
    
        template <typename T>
        typename boost::enable_if<boost::is_floating_point<T>, T>::type get()
        {
            return 11.5;
        }
    
        template <typename T>
        std::string get(
              typename boost::disable_if<boost::is_floating_point<T>, T>::type* = 0, 
              typename boost::disable_if<boost::is_integral<T>, T>::type* = 0)
    
        {
            return std::string("string");
        }
    };
    
        2
  •  3
  •   Kaz Dragon    16 年前

    遵循另一个模板。以下是您想要的一般模式:

    template <typename T, bool HasTrait = false>
    struct scanner_impl;
    
    template <typename T>
    struct scanner_impl
    {
        // Implement as though the trait is false
    };
    
    template <typename T>
    struct scanner_impl<true>
    {
        // Implement as though the trait is true
    };
    
    // This is the one the user uses
    template <typename T>
    struct scanner : scanner_impl<T, typename has_my_trait<T>::value>
    {
    };