【问题标题】:c++: alternative to 'std::is_fundamental'?c ++:'std :: is_fundamental'的替代品?
【发布时间】:2013-05-29 06:58:21
【问题描述】:

在模板类中的函数中,我试图区分原始类型和其他类型。

在 c++ 11 中你可以这样做:

if(std::is_fundamental<T>::value)
{
    // Treat it as a primitive
}
else
{
    //Treat it otherwise
}

如果我错了,请纠正我,这不仅在 c++ 11 中。

在早期版本的 c++ 中是否有替代方案?

【问题讨论】:

    标签: c++ c++11 typetraits


    【解决方案1】:

    你可以像这样在 C++03 中使用Boost's type traits

    #include  <boost/type_traits/is_fundamental.hpp>
    
    ...
    
    if(boost::is_fundamental<T>::value)
    {
        // Treat it as a primitive
    }
    else
    {
        //Treat it otherwise
    }
    

    我想这也应该适用于 C++98。

    【讨论】:

    • 谢谢。 +1 include
    【解决方案2】:

    使用此代码,您可能会遇到麻烦。如果您需要区分不同的类型特征,则必须在编译时完成,而不是在运行时完成。根据您正在执行的操作,if 的两个分支之一可能无法编译。所以最好转发到专门的函数:

    void operation_impl(boost::true_type /*other params*/) {
      // Treat it is primitive 
    }
    
    void operation_impl(boost::false_type /*other params*/) {
      // Treat it otherwise
    }
    
    template<class T>
    void operation(/* params*/) {
      operation_impl(boost::is_fundamental<T>::type() /*other params*/);
    }
    

    使用这种实现技术,只需要编译使用的分支(即正确)。

    编辑:

    这里有一些附加信息。这个问题的解决方案与模板的实例化有关。我从is_fundamental 切换到is_array 以显示操作可能会如何失败。

    让我们从第一个例子开始:

    template <class T>
    void fun(T t) {
        if(boost::is_array<T>::value)
        {
            std::cout << "true" << std::endl;
        }
        else
        {
            std::cout << "false" << std::endl;
        }
    }
    
    void f(int i) {
        fun(i);
    }
    

    它将编译并运行,编译器将看到 if 语句的只有一个分支将被使用,并将另一个分支作为未使用的代码删除。

    在我的第二个示例中,我将在使用数组操作的情况下做一些事情:

    template<class T>
    void fun(T& t) {
        if(boost::is_array<T>::value)
        {
            std::cout << t[0];
        }
        else
        {
            std::cout << t;
        }
    }
    
    void f(int i) {
        fun(i);
    }
    

    现在它不会编译。原因是 int 作为模板参数 t[0] 格式不正确。您不能在编译时使用此运行时语句来区分代码中需要的类型属性(在此示例中是数组的属性和t[0] 的使用)。

    在第三个示例中,我们将通过函数重载来区分编译时间:

    template<class T>
    void fun_impl(boost::true_type, T& t) {
        std::cout << t[0];
    }
    
    template<class T>
    void fun_impl(boost::false_type, T& t) {
        std::cout << t;
    }
    
    template<class T>
    void fun(T& t) {
        fun_impl(typename boost::is_array<T>::type(),t);
    }
    
    void f(int i) {
        fun(i);
    }
    

    这里的is_array&lt;T&gt;::typetrue_typefalse_type。这个结果被用作在编译时选择fun_impl的正确重载的选择器,并且只有选择的重载被实例化和编译。

    通常,此类技术用于在编译时选择最佳实现,该实现可能仅在类型具有某些属性时才可编译。

    第二次编辑:

    如果static if 是语言的一部分,这当然会改变。

    【讨论】:

    • 您能否详细说明我在使用其他方法时可能遇到的问题?或者您可以添加对解释的引用吗?我没看懂你写的内容。
    • 谢谢! +1 用于详细说明。不过我仍然有一个问题:据我了解,您的意思是编译代码,并节省不必要的代码的编译。鉴于我的代码可以编译,使用第一种方法在运行时可能会遇到实际问题(如意外行为)吗?
    • @Subway no 我认为编译器会将您的 boost::is_fundamental::value 视为常量,并将删除未使用的代码,因此没有运行时开销,也没有 UB。方法是完全编译它。 const value 成员用于与 std::enable_if 一起使用(作为一个完整的模板参数),当然也用于演示(如打印值)。我认为出于其他所有目的,您应该通过函数重载进行游览。
    猜你喜欢
    • 1970-01-01
    • 2020-01-21
    • 2020-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多