gpt4 book ai didi

c++ - 使用 "if constexpr"和 SFINAE 禁用分支

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:26:37 25 4
gpt4 key购买 nike

我想在编译时启用/禁用分支,这取决于是否可以使用某些参数调用函数。if constexpr 条件必须包含什么?我可以通过 std::result_of(decltype(add)(A, B)) 获取结果类型,但是如何检查结果类型是否有效? (即如何将此信息转换为 bool?)

const auto add = [](const auto a, const auto b) { return a + b; };

const auto subtract = [](const auto a, const auto b) { return a - b; };

template <typename A, typename B>
void foo(A a, B b) {

if constexpr ( /* can add(a, b) be called? */ ) {
std::cout << "result of add: " << add(a, b) << std::endl;
}

if constexpr ( /* can subtract(a, b) be called? */ ) {
std::cout << "result of subtract: " << subtract(a, b) << std::endl;
}
}

最佳答案

首先,您需要使您的 lambda SFINAE 友好。

#define RETURNS(...)\
noexcept(noexcept(__VA_ARGS__))\
->decltype(__VA_ARGS__)\
{ return __VA_ARGS__; }

const auto add = [](const auto a, const auto b) RETURNS( a + b );

const auto subtract = [](const auto a, const auto b) RETURNS( a - b );

现在可以在 SFINAE 上下文中测试加法和减法。

namespace details {
template<class, class, class...>
struct can_invoke:std::false_type {};
template<class F, class...Args>
struct can_invoke<F, std::void_t< std::result_of_t< F&&(Args&&...) > >, Args... >:
std::true_type
{};
}
template<class F, class...Args>
using can_invoke_t = details::can_invoke<F, Args...>;

template<class F, class...Args>
constexpr can_invoke_t< F, Args... >
can_invoke( F&&, Args&&... ){ return {}; }

我们准备好了:

template <typename A, typename B>
void foo(A a, B b) {

if constexpr ( can_invoke( add, a, b ) ) {
std::cout << "result of add: " << add(a, b) << std::endl;
}

if constexpr ( can_invoke( subtract, a, b ) {
std::cout << "result of subtract: " << subtract(a, b) << std::endl;
}
}

这是 ;在 更尴尬,在更优雅,因为它们已经有一个 can invoke 类型特征(它处理更多的极端情况;但是,它还希望您使用 std::invoke 调用 add)。


我有点喜欢这个把戏:

template<class F>
constexpr auto invoke_test( F&& ) {
return [](auto&&...args) ->
can_invoke_t<F, decltype(args)...>
{ return {}; };
}

template <typename A, typename B>
void foo(A a, B b) {

if constexpr ( invoke_test( add )( a, b ) ) {
std::cout << "result of add: " << add(a, b) << std::endl;
}

if constexpr ( invoke_test( subtract )( a, b ) {
std::cout << "result of subtract: " << subtract(a, b) << std::endl;
}
}

其中 invoke_test 接受一个可调用对象,并返回一个可调用对象,该可调用对象的唯一工作是回答“使用您传递给我的参数调用原始可调用对象”。

关于c++ - 使用 "if constexpr"和 SFINAE 禁用分支,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49015290/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com