c++ - 使用 std::enable_if 时进行优化

标签 c++ templates c++17 variadic-templates sfinae

考虑这段代码:

#include <iostream>
#include <type_traits>

template <std::size_t N> void bar() { std::cout << "bar<" << N << ">() called.\n"; }
template <std::size_t N> void hit() { std::cout << "hit<" << N << ">() called.\n"; }

template <typename T> struct evaluate : std::bool_constant<std::is_integral_v<T>> {
    static constexpr std::size_t size = sizeof(T);  // Simplified for illustration only.
};

void foo() { }

template <typename T, typename... Args>
std::enable_if_t<!evaluate<T>::value> foo (const T&, const Args&...);

template <typename T, typename... Args>
std::enable_if_t<evaluate<T>::value> foo (const T&, const Args&... args) {
    bar<evaluate<T>::size>();
    // Do whatever.
    foo(args...);
}

template <typename T, typename... Args>
std::enable_if_t<!evaluate<T>::value> foo (const T&, const Args&... args) {
    hit<evaluate<T>::size>();
    // Do whatever, but different from the previous foo overload.
    foo(args...);
}

int main() {
    foo (5, "hello", true);
}


Output:
bar<4>() called.
hit<6>() called.
bar<1>() called.

如何重写上面的内容使得 evaluate<T>每次 foo 迭代只需要计算一次而不是两次?

最佳答案

你可能喜欢这个:

template <std::size_t N> void bar() { std::cout << "bar<" << N << ">() called.\n"; }
template <std::size_t N> void hit() { std::cout << "hit<" << N << ">() called.\n"; }

template <typename T>  
struct evaluate : std::bool_constant<std::is_integral_v<T>> 
{   
    static constexpr std::size_t size = sizeof(T);  // Simplified for illustration only.
};  

void foo() { } 

template <typename T, typename... Args>
void foo( const T&, const Args&... args) 
{   
    using X = evaluate<T>;

    if constexpr ( X::value )
    {   
        bar<X::size>();
    }   
    else
    {   
        hit<X::size>();
    }   

    foo( args... );
}   


int main() {
    foo (5, "hello", true);
}

它只“调用”一次 evaluate<T> ,这并不重要,但可能更容易阅读。所有模板代码仅在实例化过程中使用,这只是个人喜好问题。

正如您提到的 c++17你可以使用 constexpr if在您的示例中完全摆脱 SFINAE。这也使得在 foo 的两种变体中重用公共(public)代码行成为可能,这非常好。您可以相信,可执行文件不会有太大差异,但我认为可维护性要好得多!

关于c++ - 使用 std::enable_if 时进行优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49636070/

相关文章:

c++ - 为什么我的循环范围不会改变元素?

c++ - Intel 编译器 (C++) 问题与 std::vector 上的 OpenMP 缩减

c++ - 将指向类的指针设置为 0 时出现错误 : does not name a type,

c++ - 我可以专门化运算符<<吗?

c++ - 为什么 std::is_invocable 不能处理转发?

c++ - 创建别名时静态断言模板参数检查

c++ - 如何在 c++17 中传递 Callable 对象以与 std::invoke 一起使用

C++ try-catch 异常处理约定

c++ - "Retroactive Union"- 可以吗?

javascript - polymer 、模板不会评估 true 和绑定(bind)