三元运算符和constexpr

时间:2018-10-10 22:23:12

标签: c++ c++17 constexpr if-constexpr

在某些情况下,有时我想基于某些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;
}

4 个答案:

答案 0 :(得分:3)

另一种选择是使用标签分配:

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;
}

答案 1 :(得分:2)

不确定是否更好,但是使用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);
}

Demo

答案 2 :(得分:1)

这应该有效:

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;
}

live example

答案 3 :(得分:1)

  

我在下面的代码中有解决方法,但是它很冗长。有更好的方法吗?

使用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"}; }