首先,我已经看到了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