在 C++ 11 中,如果函数参数是编译时常量,是否有任何方法可以进行分支?

lig*_*use 10 c++ templates compile-time-constant c++11

无论如何,我是否可以判断函数参数在 C++ 11 中是否是编译时间常数?我想根据结果对函数体进行分支。例如,如下所示;

template <T>
size_t get_length(const T &t)
{
    return t.size();
}

template <typename T, size_t N>
size_t get_length(const std::array<T, N> &t)
{
    return N;
}

// Maybe some template
??? foo(size_t length)
{
    ...
    // If length could be evaluated at compile time,
    return std::array<int, length>{};

    ...
    // Otherwise,
    return std::vector<int>(length);
}


// ??? and auto should be std::array if bar is std::array, std::vector if bar is std::vector or etc.
auto x = foo(get_length(bar));

Run Code Online (Sandbox Code Playgroud)

我相信这需要两项任务;首先,它应该能够确定一个值是否在编译时可评估。其次,如果可能的话,将值转换为编译时间常数。

无论如何有人可以做到这一点吗?或者有什么理由这是不可能的吗?似乎有人说使用模板函数,但这迫使调用者输入编译时间常数,而不是我想要的。

eca*_*mur 9

get_length通过更改为返回以下内容,这是合理可能的integral_constant

template <typename T, size_t N>
auto get_length(const std::array<T, N> &t)
{
    return std::integral_constant<std::size_t, N>();
}
Run Code Online (Sandbox Code Playgroud)

然后,要使用结果,

auto foo(auto length) {
    // If length could be evaluated at compile time,
    if constexpr (requires { typename std::array<int, length>; })
        return std::array<int, length>{};
    // Otherwise,
    else
        return std::vector<int>(length);
}
Run Code Online (Sandbox Code Playgroud)

它使用从 C++14 到 C++20 的设施(简洁的模板、if constexpr概念),但如果需要,可以直接向后移植到 C++11。