C ++模板提取布尔参数

Ziq*_*Liu 3 c++ templates

我想从模板参数中提取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 ++请使用此类功能,也请告诉我,谢谢!

Adr*_*vry 6

嗯,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/

这个网站是一个很好的工具,可以检查编译器(ClangGCCMSVC等)如何处理您的代码。


J. *_*rez 5

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 仅在编译时运行,它确实可以满足您的要求。


bgu*_*ura 4

一种可能性如下

#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)