三元运算符和 if constexpr

Ternary operator and if constexpr

本文关键字:if constexpr 运算符 三元      更新时间:2023-10-16

我有时根据某些bool调用 2 个返回不同类型的constexpr函数并将其分配给常量auto

不幸的是,三元运算符需要类型是"相似"的。

我在下面的代码中有解决方法,但它非常冗长。有没有更好的方法?

#include <iostream>
#include <string>
constexpr int get_int(){
return 47;
}
constexpr std::string_view get_string(){
return "47";
}
constexpr bool use_str = false;
constexpr auto get_dispatch(){
if constexpr(use_str){
return get_string();
} else{
return get_int();
}
}
int main()
{
// what I want : constexpr auto val =  use_str ? get_string():get_int();
// what works:
constexpr auto val = get_dispatch();
std::cout << val << std::endl;
}

另一种选择是使用标记调度:

constexpr int get(std::false_type) {
return 47;
}
constexpr std::string_view get(std::true_type) {
return "47";
}
int main() {
constexpr auto val = get(std::bool_constant<use_str>{});
std::cout << val << std::endl;
}

不确定它更好,但有了std::variant

int main()
{
using my_variant = std::variant<int, std::string_view>;
constexpr auto val =  use_str ? my_variant{get_string()} : my_variant{get_int()};
std::visit([](const auto& v) {std::cout << v << std::endl;}, val);
}

演示

这应该有效:

template <bool>
struct value_chooser;
template<>
struct value_chooser<true>
{
static constexpr auto value = "47";
};
template<>
struct value_chooser<false>
{
static constexpr auto value = 47;
};
int main()
{
auto value1 = value_chooser<true>::value;
auto value2 = value_chooser<false>::value;
}

现场示例

我在下面的代码中有解决方法,但它非常冗长。有没有更好的方法?

使用 C++17,您可以使用if constexpr在我看来这是一个很好的解决方案。

如果你真的想要一些不同的东西,我提出了一种基于模板功能完全专业化的方法(Evg 和 Slava 解决方案之间的混合(

我的意思是

#include <iostream>
#include <string>
template <bool>
constexpr auto get_value ()
{ return 47; }
template <>
constexpr auto get_value<true> ()
{ return std::string_view{"47"}; }
int main()
{
constexpr auto use_str = false;
constexpr auto val     = get_value<use_str>();
std::cout << val << std::endl;
}

正如 Slava 所指出的,具有默认版本和针对一种情况的显式专用化的模板函数可能不太易读。

因此,如果您更喜欢更冗长但更具可读性的变体,您可以为get_value()编写两个显式专用化,如下所示

template <bool>
constexpr auto get_value ();
template <>
constexpr auto get_value<false> ()
{ return 47; }
template <>
constexpr auto get_value<true> ()
{ return std::string_view{"47"}; }