'if'带模板参数或SFINAE是首选? [英] 'if' with template parameters or SFINAE is preferred?

查看:113
本文介绍了'if'带模板参数或SFINAE是首选?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首选是:

 模板< typename T& 
bool isNotZero(const T& a)
{
if(std :: is_floating_point< T> value)return abs(a)> std :: numeric_limits< T> :: epsilon();
else return a;
}

或者:

  template< typename T> 
std :: enable_if< std :: is_floating_point< T> :: value,bool> :: type
isNotZero(const T& a){return abs(a) std :: numeric_limits< T> :: epsilon(); }

template< typename T>
std :: enable_if< std :: is_integral< T> :: value,bool> :: type
isNotZero(const T& a){return a; }

我通常使用第一个类型避免许多版本的函数。



我相信它是完全一样的。



在操作码阶段优化的第一个版本和模板实例化阶段的第二个版本。

解决方案


我相信它是完全一样的。


$



在第一个版本中,您正在使用在运行时评估的条件语句,但决定执行哪个分支的条件可以在编译时 决定

>

因此,两个分支都必须编译,无论输入的类型是什么,即使我们知道在编译时只有其中一个将被执行

在第二种情况下,你只编译(并执行,当然)适合输入类型的



现在即使在这种特殊情况下,你选择的方法也不会改变,有条件的执行是由编译时条件应该通过编译时构造(SFINAE和模板重载)来表示,而如果应用于依赖于运行时状态的条件系统。



第一种方法是不可能的,例如,如果条件包含的代码的两个分支仅当相应的分支被执行时编译。考虑这两种类型:

  struct X 
{
X(int){}
};

struct Y
{
Y(){}
};

以下功能模板:

  template< typename T> 
T foo(const T& a)
{
if(std :: is_constructible< T,int> :: value)
{
return T );
}
else
{
return T();
}
}

现在以下调用都不合法: / p>

  foo(X()); //错误! X不是默认可构造的
foo(Y()); //错误! Y不能从int中构造

这就是说,一般来说,用于处理编译时条件执行的是模板重载+ SFINAE (或者可能涉及类模板特化的等效结构)。



当然,您可以使用 degenerate 案例(例如这个)来允许您使用其他工具,但如果我们在寻找概念上正确的设计



如果像 static if ,但现在不是这样 - 甚至在不久的将来,似乎。


Preferred is this:

template<typename T>
bool isNotZero(const T &a)
{
    if (std::is_floating_point<T>::value) return abs(a) > std::numeric_limits<T>::epsilon();
    else return a;
}

Or this:?

template<typename T>
std::enable_if<std::is_floating_point<T>::value, bool>::type
isNotZero(const T &a) { return abs(a) > std::numeric_limits<T>::epsilon(); }

template<typename T>
std::enable_if<std::is_integral<T>::value, bool>::type
isNotZero(const T &a) { return a; }

I usually use the first type to avoid many versions of function.

I believe it is exactly the same.

The first version optimized in opcode stage and the second version in template instantiation stage.

解决方案

I believe it is exactly the same.

I would not say it is exactly the same.

In the first version, you are using a conditional statement which is evaluated at run-time, but the condition that decides which branch shall be executed can be (and is) decided at compile-time.

Therefore, both of your branches must compile and will be compiled no matter what the type of the input is, even though we known at compile-time that only one of them will be executed and the other will be dead - I expect the compiler would issue a warning here.

In the second case, you only compile (and execute, of course) what is appropriate for the type of the input. In my opinion, this makes the second approach superior.

Now even though in this particular situation it will likely make no difference which approach you choose, conditional executions that are decided by compile-time conditions should be expressed by means of compile-time constructs - SFINAE and template overloading, while if should be used for conditions that depend on the run-time state of the system.

The first approach would not be possible, for instance, if the two branches of the conditional contained code that compiles only when the corresponding branch is executed. Consider these two types:

struct X
{
    X(int) { }
};

struct Y
{
    Y() { }
};

And the following function template:

template<typename T>
T foo(const T &a)
{
    if (std::is_constructible<T, int>::value)
    {
        return T(42);
    }
    else
    {
        return T();
    }
}

Now none of the following calls would be legal:

foo(X()); // ERROR! X is not default-constructible
foo(Y()); // ERROR! Y is not constructible from an int

This alone suggests that, in general, the appropriate tool for handling compile-time conditional execution is template overloading + SFINAE (or equivalent constructs possibly involving class template specializations).

Sure, there are degenerate cases (such as this one) that allow you using other tools, but if we are looking for conceptually correct design guidelines, I believe there is a clear winner here.

Things would of course be different if something like static if existed in C++, but this is not the case at the moment - and not even in a near future, it seems.

这篇关于'if'带模板参数或SFINAE是首选?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆