用于替换C++14中if constexpr的GENERIC解决方案



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

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

下面你会发现一个使用if constexpr的小例子——我不需要下面提到的情况的解决方案——而是一个通用的解决方案,它可以在大多数情况下用作if constexpr的替代品,如果不是无处不在的话。您可以假设我正在将带有if constexpr的C++17代码移植到C++14——最简单的方法是什么?

我正在考虑解决方案,可能如下所示,但不确定如何实现:if<condition>(func1).elif<condition2>(func2).else(func3)其他想法也非常受欢迎。

要测试的C++17代码:

#include <string>
template<class T>
constexpr bool value = true;
template<>
constexpr bool value<std::string> = false;
template<class T>
void method(const T& arg) {
if constexpr (value<T>) {
if (!arg) return;
}
//mylogic(arg);
}
int main() {
std::string arg;
method(arg);
int arg2;
method(arg2);
return 0;
}

您可以用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。

有几种方法可以修复它。

现在,由于您创建了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

相关内容

最新更新