可以在编译时评估使用 std::is_same<> 的条件吗?
Can this condition using std::is_same<> be evaluated at compile time?
我知道 constexpr
函数不必在编译时求值,但如果可能的话它们会被求值。以下if
的条件是否在编译时求值?
template <typename T> inline std::string toString(const T& arg, int decPlaces)
{
if (!std::is_same<T, float>::value && !std::is_same<T, double>::value)
return std::to_string(arg);
// Else go on strip digits after decimal point
}
我知道在 C++17 中有 if constexpr
保证在编译时求值,但我只是想知道在这种情况下是否可以在编译时求值,因为 bool
从 is_same
返回的是 constexpr
。比如不能使用C++17的情况。
如果您想确定,请检查生成的程序集。但是,编译器极有可能确实会用无条件的 return
替换 if
(如果 T
是 float
或 double
),或者删除它完全(否则)。这是一个相当基本的优化。
您需要确保 T
的所有代码路径为 float
或 double
,其他代码路径需要同时有效才能编译。如果 if
和 else
中的代码对特定类型无效,您 运行 就会出错。
对于应用的确切优化,您需要检查汇编代码。
考虑一下你的代码的这个稍微修改的版本(这样控制流就不能到达这样一个非void
函数的结尾):
template <typename T> inline std::string toString(const T& arg, int decPlaces)
{
if (!std::is_same<T, float>::value && !std::is_same<T, double>::value)
return std::to_string(arg);
return ""; // <-- added
}
通过显式实例化 T=float
的模板函数:
template std::string toString<float>(const float&, int);
然后在启用g++
6.4.0和-O2
的情况下进行编译,为x86生成以下汇编代码 平台:
__Z8toStringIfESsRKT_i:
pushl %ebx
subl , %esp
movl 48(%esp), %ebx
leal 31(%esp), %eax
movl $LC0, 4(%esp)
movl %eax, 8(%esp)
movl %ebx, (%esp)
call __ZNSsC1EPKcRKSaIcE
addl , %esp
movl %ebx, %eax
popl %ebx
ret
上面的代码中没有条件。
所以,对于这个编译器和平台,条件实际上是在编译时评估的。您可以针对您的目标编译器和平台进行类似的操作。
我知道 constexpr
函数不必在编译时求值,但如果可能的话它们会被求值。以下if
的条件是否在编译时求值?
template <typename T> inline std::string toString(const T& arg, int decPlaces)
{
if (!std::is_same<T, float>::value && !std::is_same<T, double>::value)
return std::to_string(arg);
// Else go on strip digits after decimal point
}
我知道在 C++17 中有 if constexpr
保证在编译时求值,但我只是想知道在这种情况下是否可以在编译时求值,因为 bool
从 is_same
返回的是 constexpr
。比如不能使用C++17的情况。
如果您想确定,请检查生成的程序集。但是,编译器极有可能确实会用无条件的 return
替换 if
(如果 T
是 float
或 double
),或者删除它完全(否则)。这是一个相当基本的优化。
您需要确保 T
的所有代码路径为 float
或 double
,其他代码路径需要同时有效才能编译。如果 if
和 else
中的代码对特定类型无效,您 运行 就会出错。
对于应用的确切优化,您需要检查汇编代码。
考虑一下你的代码的这个稍微修改的版本(这样控制流就不能到达这样一个非void
函数的结尾):
template <typename T> inline std::string toString(const T& arg, int decPlaces)
{
if (!std::is_same<T, float>::value && !std::is_same<T, double>::value)
return std::to_string(arg);
return ""; // <-- added
}
通过显式实例化 T=float
的模板函数:
template std::string toString<float>(const float&, int);
然后在启用g++
6.4.0和-O2
的情况下进行编译,为x86生成以下汇编代码 平台:
__Z8toStringIfESsRKT_i:
pushl %ebx
subl , %esp
movl 48(%esp), %ebx
leal 31(%esp), %eax
movl $LC0, 4(%esp)
movl %eax, 8(%esp)
movl %ebx, (%esp)
call __ZNSsC1EPKcRKSaIcE
addl , %esp
movl %ebx, %eax
popl %ebx
ret
上面的代码中没有条件。
所以,对于这个编译器和平台,条件实际上是在编译时评估的。您可以针对您的目标编译器和平台进行类似的操作。