我想从模板参数中提取bool值,并在代码的其他地方使用该值。(更具体地说,我希望编译时使用if-else)。
template<bool enable_xx>
struct A {
void DoSomething() {
if (enable_xx) {
// do something
} else {
// do something else
}
}
}
Run Code Online (Sandbox Code Playgroud)
我正在使用C ++ 11,但是如果更高版本的C ++请使用此类功能,也请告诉我,谢谢!
嗯,if (enable_xx)编译时就可以解决。大多数编译器会优化您的函数以防止在运行时检查条件,但您不能确定。
处理此问题的最佳方法是使用C++17if constexpr功能。它允许您指定 if 语句依赖于一个或多个。constexpr
给出这段代码:
#include <iostream>
template <bool verbose>
void SayHello()
{
if (verbose)
{
std::cout << "Hello guys!\n";
}
else
{
std::cout << "Hi!\n";
}
}
Run Code Online (Sandbox Code Playgroud)
反汇编(使用 x64 msvc v19.20)如下SayHello<true>()所示:
void SayHello<1>(void) PROC ; SayHello<1>, COMDAT
$LN5:
sub rsp, 40 ; 00000028H
xor eax, eax
cmp eax, 1
je SHORT $LN2@SayHello
lea rdx, OFFSET FLAT:$SG31024
lea rcx, OFFSET FLAT:std::basic_ostream<char,std::char_traits<char> > std::cout ; std::cout
call std::basic_ostream<char,std::char_traits<char> > & std::operator<<<std::char_traits<char> >(std::basic_ostream<char,std::char_traits<char> > &,char const *) ; std::operator<<<std::char_traits<char> >
jmp SHORT $LN3@SayHello
$LN2@SayHello:
lea rdx, OFFSET FLAT:$SG31025
lea rcx, OFFSET FLAT:std::basic_ostream<char,std::char_traits<char> > std::cout ; std::cout
call std::basic_ostream<char,std::char_traits<char> > & std::operator<<<std::char_traits<char> >(std::basic_ostream<char,std::char_traits<char> > &,char const *) ; std::operator<<<std::char_traits<char> >
$LN3@SayHello:
add rsp, 40 ; 00000028H
ret 0
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,程序将在运行时评估条件。
对于 C++17 if constexpr( if (verbose)==> if constexpr (verbose)),使用相同编译器选项的反汇编如下所示:
void SayHello<1>(void) PROC ; SayHello<1>, COMDAT
$LN3:
sub rsp, 40 ; 00000028H
lea rdx, OFFSET FLAT:$SG31017
lea rcx, OFFSET FLAT:std::basic_ostream<char,std::char_traits<char> > std::cout ; std::cout
call std::basic_ostream<char,std::char_traits<char> > & std::operator<<<std::char_traits<char> >(std::basic_ostream<char,std::char_traits<char> > &,char const *) ; std::operator<<<std::char_traits<char> >
add rsp, 40 ; 00000028H
ret 0
Run Code Online (Sandbox Code Playgroud)
您可以看到该if语句从生成的代码中消失了。编译器对其进行了优化。
您还可以注意到,反汇编与该函数的非模板化版本完全相同:
void SayHelloTrue()
{
std::cout << "Hello guys!\n";
}
Run Code Online (Sandbox Code Playgroud)
因此,如果您可以使用 C++17,请始终指定您的ifas constexpr(如果它们在编译时可评估)以优化您的代码,即使在调试模式下也是如此(无优化标志)。如果您无法使用 C++17,请假设您的编译器拥有最终决定权,并且会或不会优化您的代码,具体取决于优化标志及其功能。
我分享的反汇编是使用以下命令生成的: https: //godbolt.org/
这个网站是一个很好的工具,可以检查编译器(Clang、GCC、MSVC等)如何处理您的代码。
C ++ 17提供了一种使用if constexpr以下方法执行此操作的方法:
template<bool enable_xx>
struct A {
void DoSomething() {
if constexpr(enable_xx) {
// do something
} else {
// do something else
}
}
};
Run Code Online (Sandbox Code Playgroud)
if constexpr 仅在编译时运行,它确实可以满足您的要求。
一种可能性如下
#include <iostream>
template<bool isTrue>
struct A;
template<>
struct A<true>
{
void DoSomething()
{
std::cout << "You did it!" << std::endl;
}
};
template<>
struct A<false>
{
void DoSomething()
{
std::cout << "You did not do it!" << std::endl;
}
};
int main(int argc, char** argv)
{
A<true> a;
A<false> b;
a.DoSomething();
b.DoSomething();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
产生以下输出:
You did it!
You did not do it!
Run Code Online (Sandbox Code Playgroud)