【问题标题】:How can I write a function template for all types with a particular type trait?如何为具有特定类型特征的所有类型编写函数模板?
【发布时间】:2010-03-29 10:35:20
【问题描述】:

考虑以下示例:

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 其他整数类型(如charunsigned int)时失败。读取这些类型的代码与读取int 的代码完全相同。我可以为我想阅读的所有其他整数类型复制代码,但我宁愿为所有整数类型定义一个函数模板。

我尝试了以下方法:

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

这就像一个魅力,但我不确定如何让Scanner::get&lt;string&gt;() 再次发挥作用。那么,我该如何编写代码,以便我可以执行 scanner.get&lt;string&gt;()scanner.get&lt;any integral type&gt;() 并有一个定义来读取所有整数类型?

更新:额外问题:如果我想根据某些特征接受多个类别的课程怎么办?例如:如果我想要三个 get 函数分别接受 (i) 整数类型 (ii) 浮点类型 (iii) 字符串,我应该如何解决这个问题。

【问题讨论】:

    标签: c++ metaprogramming enable-if


    【解决方案1】:
    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");
        }
    };
    

    【讨论】:

    • 我会说你可以使用boost::mpl::and_boost::mpl::or_ 来组合disable_if 中的参数。不过+1 :)
    • 您也可以使用 Boost 库中的 ice_andice_or
    【解决方案2】:

    遵从另一个模板。这是您想要的一般模式:

    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>
    {
    };
    

    【讨论】:

    • 以这种方式添加间接性的好主意。如果您不使用bool,而是使用enum 作为特征开关,它可能会变得更加灵活。
    • @xtofl:是的。这也可以回答奖金问题。
    猜你喜欢
    • 2012-08-28
    • 2016-02-05
    • 1970-01-01
    • 1970-01-01
    • 2019-12-08
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    • 1970-01-01
    相关资源
    最近更新 更多