首页 > 解决方案 > 在 constexpr 函数中创建空右值引用是否合法?

问题描述

我正在尝试std::tuple使用 constexpr 函数在编译时获取 a 的大小。

我写了这个,我认为它可能很容易使用并且可以给出明确的错误提示:

template<typename... TArgs>
constexpr int get_tuple_size(const std::tuple<TArgs...>&) { return sizeof...(TArgs); }

很快我意识到我不想构建一个std::tuple真的,所以我尝试了这个:

#include <cstdio>
#include <tuple>
template<typename... TArgs>
constexpr int get_tuple_size(std::tuple<TArgs...>&&) { return sizeof...(TArgs); }
template<typename T>
constexpr T&& make_rvalue() {
    return ((T&&)*(T*)0);
}
int main() {
    printf("%d\n", get_tuple_size(make_rvalue<std::tuple<int, double, float&>>()));
    return 0;
}

编辑:此代码可以在Clang 7.0.1 GCC 9.2.0 VS2019

这段代码符合我的所有要求,但它真的合法吗?

我的意思是,当我编写((T&&)*(T*)0)一个非 constexpr 函数时,它给出了一个错误。

错误 C4854:将取消引用的空指针绑定到引用具有未定义的行为

顺便问一下,有没有更好的解决方案来解决它?

我试过这个:

    template<typename T>
    struct is_tuple {
        static constexpr bool value = false;
    };
    template<typename... TArgs>
    struct is_tuple<std::tuple<TArgs...>> {
        static constexpr bool value = true;
    };
    template<typename T>
    constexpr bool is_tuple_v = is_tuple<T>::value;
    template<typename T>
    struct sizeof_tuple {
        static_assert(is_tuple_v<T>, "==========>sizeof_tuple input type isn't std::tuple");
    };
    template<typename... TArgs>
    struct sizeof_tuple<std::tuple<TArgs...>> {
        static constexpr size_t value = sizeof...(TArgs);
    };
    template<typename T>
    constexpr size_t sizeof_tuple_v = sizeof_tuple<T>::value;

但是如果你输入了错误的类型,错误提示不会指向你引用sizeof_tuple_v<T>的地方,而是声明本身。

标签: c++templatesrvalue-referencervalue

解决方案


推荐阅读