在 C++14 中替换 if constexpr 的通用解决方案

问题描述

首先,我已经看到了 Constexpr if alternative,但这没有帮助。

我更新了帖子以明确说明通用解决方案的必要性。 我需要的是在 C++14 中使用 C++17 if constexpr 潜力的通用解决方案。也许,我们可以在这里lambdas 和/或 boost::hana 做点什么?

您会在下面找到一个使用 if constexpr 的小例子 - 我不需要仅针对下面提到的情况的解决方案 - 而是一个通用的解决方案,可以在大多数情况下作为 { 的替代应用{1}} 如果不是无处不在。 您可以假设我正在将带有 if constexpr 的 C++17 代码移植到 C++14 - 最简单的方法是什么?

我正在考虑解决方案,可能如下所示,但不确定如何实现: if constexpr 其他想法也非常受欢迎。

要测试的 C++17 代码

if<condition>(func1).elif<condition2>(func2).else(func3)

解决方法

您可以使用 std::enable_if 以老式方式完成此操作,方法是将类型相关代码移动到具有特殊功能的单独函数中:

#include <string>
template<class T>
constexpr bool value = true;

template<>
constexpr bool value<std::string> = false;

template<class T,std::enable_if_t<value<T>,bool> = true>
bool is_unset(const T& arg)
{
    return !arg;
}

template<class T,std::enable_if_t<!value<T>,bool> = true>
bool is_unset(const T& arg)
{
    return false;
}

template<class T>
void method(const T& arg) {
    if (is_unset<T>(arg)) {
        return;
    }
    //mylogic(arg);
}

int main() {
    std::string arg;
    method(arg);

    int arg2;
    method(arg2);

    return 0;
}
,

这是mcve to start with

有几种方法可以修复它。

现在,由于您创建了 value 模板来对 std:string 进行特殊处理,因此可以通过简单的重载来实现:

template<class T>
void method(const T& arg) {
    if (!arg) return;
    mylogic(arg);
}

void method(const std::string& arg) {
    mylogic(arg);
}

https://godbolt.org/z/PeWdbadxK

现在假设 value 是更复杂的东西,它可以是这样的:

template<class T>
std::enable_if_t<value<T>> method(const T& arg) {
    if (!arg) return;
    mylogic(arg);
}

template<class T>
std::enable_if_t<!value<T>> method(const T& arg) {
    mylogic(arg);
}

https://godbolt.org/z/Mjvfr7qqb

显然您正在尝试处理 T 无法转换为 bool 的情况,因此您可以这样做:

template<class...>
using void_t = void;

template<class T,class U = void>
constexpr bool value = false;

template<class T>
constexpr bool value<T,void_t<decltype(!std::declval<T>())>> = true;

template<typename T>
void mylogic(T&& arg)
{
    std::cout << std::forward<T>(arg) << '\n';
}

template<class T>
std::enable_if_t<value<T>> method(const T& arg) {
    if (!arg) return;
    mylogic(arg);
}

template<class T>
std::enable_if_t<!value<T>> method(const T& arg) {
    mylogic(arg);
}

https://godbolt.org/z/46n87xd6a

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...