【问题标题】:How to check that template's parameter type is integral?如何检查模板的参数类型是否完整?
【发布时间】:2010-08-11 13:01:29
【问题描述】:

在一些标准模板函数的描述中,我看到了类似的内容:

如果模板参数是整数类型,那么行为就是这样。
否则就是这样那样。

如何进行类似的测试?也许是dynamic_cast?

由于我编写的函数是供我个人使用的,我可以依靠自己只提供正确的参数,但为什么会错过学习的机会呢? :)

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    除了其他答案之外,应该注意的是,测试可以在运行时使用,也可以在编译时使用,以根据类型是否为整数来选择正确的实现:

    运行时版本:

    // Include either <boost/type_traits/is_integral.hpp> (if using Boost) 
    // or <type_traits> (if using c++1x)
    // In the following, is_integral shoudl be prefixed by either boost:: or std::
    
    template <typename T>
    void algorithm(const T & t)
    {
        // some code
    
        if (is_integral<T>::value)
        {
            // operations to perform if T is an integral type
        }
        else
        {
            // operations to perform if T is not an integral type
        }
    
        // some other code
    }
    

    但是,当算法的实现很大程度上取决于测试时,可以改进此解决方案。在这种情况下,我们将测试放在函数的顶部,然后是一个大的then 块和一个大的else 块。在这种情况下,一种常见的方法是重载函数并让编译器使用 SFINAE 选择正确的实现。一个简单的方法是使用boost::enable_if

    #include <boost/utility/enable_if.hpp>
    #include <boost/type_traits/is_integral.hpp>
    
    template <typename T>
    typename boost::enable_if<boost::is_integral<T> >::type
    algorithm(const T & t)
    {
        // implementation for integral types
    }
    
    template <typename T>
    typename boost::disable_if<boost::is_integral<T> >::type
    algorithm(const T & t)
    {
        // implementation for non integral types
    }
    

    在调用algorithm 函数时,编译器将根据模板参数是否为整数来“选择”正确的实现。

    【讨论】:

    • 我想说每个值得一提的编译器都会消除第一个示例中的死分支 - 它很简单。
    • @Georg Fritzsche:这是真的,这就是为什么我没有说任何潜在的性能提升。尽管如此,我认为重载方法更清晰:这两种实现可以分开发展,我发现最好区分什么是静态的(在编译时知道/执行)和什么是动态的(在运行时知道/执行)。但是,这可能是因为这几个月我花了太多时间进行元编程!
    • @Georg Fritzsche:另一个重要的一点是,第一个解决方案并不总是一种选择,因为在尝试执行仅适用于某些类型的操作时,它可能会导致编译器错误。例如,在积分专用算法中,我可以使用位运算符;如果我在第一个示例中这样做,则用于实例化函数的所有类型都需要为这些运算符提供支持(这是我不想强加给我算法的用户的东西!)。
    • 我知道,我没有批评其他任何东西,而且我个人更喜欢第二个版本......它只会误导阅读 “运行时版本” 当它是最无论如何都可能在编译时消除。
    • 请注意 is_integral 现在是 C++11 的标准。
    【解决方案2】:

    One possibility:

    #include <type_traits> 
    #include <iostream> 
    
    struct trivial 
    { 
        int val; 
    }; 
    
    int main() 
    { 
        std::cout << "is_integral<trivial> == " << std::boolalpha 
            << std::is_integral<trivial>::value << std::endl; 
        std::cout << "is_integral<int> == " << std::boolalpha 
            << std::is_integral<int>::value << std::endl; 
        std::cout << "is_integral<float> == " << std::boolalpha 
            << std::is_integral<float>::value << std::endl; 
    
        return (0); 
    } 
    

    然后您使用std::is_integral&lt;&gt; 来确定操作。

    【讨论】:

      【解决方案3】:

      如果您无法使用 C++11 功能,std::numeric_limits&lt;T&gt;::is_integerthe same thing 用作 std::is_integral&lt;T&gt;::value,并且可用于 C++98。

      注意98版本是intger,不是intgral

      【讨论】:

        【解决方案4】:

        Boost.TypeTraits 提供 is_integral(),如另一个响应中所述,如果您的编译器尚不支持下一个标准的 C++ 功能。

        【讨论】:

        • 可能没有,我刚刚检查过我没有 type_traits 包含文件。应该添加 'linux' 和 'gcc' 标签...
        • @davka:这些标签与 boost 无关。如果 header 丢失,那么您需要将正确的位置添加到 headers 的搜索路径或安装 boost。
        猜你喜欢
        • 2021-04-13
        • 1970-01-01
        • 2020-11-21
        • 2012-11-18
        • 1970-01-01
        • 2021-12-26
        • 2013-10-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多