一个关于 c++11 中引用的问题

2015-10-08 15:01:39 +08:00
 linux40
template <size_t N>
struct tuple_helper_get {
    template <typename T, typename... Args> constexpr static
    auto get_ref(tuple_helper<T, Args...> &t) noexcept
        -> decltype(tuple_helper_get<N - 1>::get_ref
                    (static_cast<tuple_helper<Args...> &>(t)))
    {
        return tuple_helper_get<N - 1>::get_ref(
            static_cast<tuple_helper<Args...> &>(t));    //!required from ‘ static constexpr decltype (glgltinySTL::tuple_helper_get<(N - 1)>::get_ref(static_cast<glgltinySTL::tuple_helper<Args ...>&>(t))) glgltinySTL::tuple_helper_get<N>::get_ref(glgltinySTL::tuple_helper<Arg, Args ...>&) [with T = int; Args = {char, unsigned int}; long unsigned int N = 2ul; decltype (glgltinySTL::tuple_helper_get<(N - 1)>::get_ref(static_cast<glgltinySTL::tuple_helper<Args ...>&>(t))) = unsigned int&]’
    }
    //...
};

template <>
struct tuple_helper_get<1> {
    template <typename T1, typename T2> constexpr static
    T2 &get_ref(tuple_helper<T1, T2> &t) noexcept
    {
        return (t.t2);    //!错误:用类型为‘ unsigned int ’的右值初始化类型为‘ unsigned int&’的非常量引用无效
    }                     //!错误: body of constexpr function ‘ static constexpr T2& glgltinySTL::tuple_helper_get<1ul>::get_ref(glgltinySTL::tuple_helper<T1, T2>&) [with T1 = char; T2 = unsigned int]’ not a return-statement
    //...
};

template <size_t N, typename... Args> constexpr
auto get(tuple<Args...> &t) noexcept
    -> decltype(tuple_helper_get<N>::get_ref
                (static_cast<tuple_helper<Args...> &>(t)))
{
    return tuple_helper_get<N>::get_ref(
        static_cast<tuple_helper<Args...> &>(t));    //!required from ‘ constexpr decltype (glgltinySTL::tuple_helper_get<N>::get_ref(static_cast<glgltinySTL::tuple_helper<OtherArgs ...>&>(t))) glgltinySTL::get(glgltinySTL::tuple<Args ...>&) [with long unsigned int N = 2ul; Args = {int, char, unsigned int}; decltype (glgltinySTL::tuple_helper_get<N>::get_ref(static_cast<glgltinySTL::tuple_helper<OtherArgs ...>&>(t))) = unsigned int&]’
}

void test_tuple()
{
    glgltinySTL::pair<int, unsigned> p{ -1, 1 };
    glgltinySTL::tuple<int, char, unsigned> t{ -1, 'a', 1 };
    std::cout << glgltinySTL::get<0>(t) << std::endl;
    std::cout << glgltinySTL::get<1>(t) << std::endl;
    std::cout << glgltinySTL::get<2>(t) << std::endl;        //!required from here
    std::cout << glgltinySTL::get<0>(p) << std::endl;
    std::cout << glgltinySTL::get<1>(p) << std::endl;
}

明明每个函数都传递的引用,怎么变成右值了?而且,注意到其他几个都没事,可能是
template <size_t N>
struct tuple_helper_get {//...};的问题。。。

1154 次点击
所在节点    C
11 条回复
htfy96
2015-10-08 15:23:30 +08:00
你这个函数的 constexpr 有问题?根据标准一个 constexpr 函数不能拥有 a reference to a variable unless it was initialized with a constant expression or is a non-static data member of a temporary object whose lifetime begain within this expression
htfy96
2015-10-08 15:27:21 +08:00
你的那个 tuple 的构造函数不是 constexpr 函数,因而产生的 t 不是 constant expression ,所以 constexpr 函数不能正确处理关于 t 的引用
linux40
2015-10-08 17:38:01 +08:00
@htfy96 谢谢啦,等下我把 constexpr 去掉, tuple 不是 constexpr 的。。。
linux40
2015-10-11 18:10:06 +08:00
@htfy96 还是一样的错误。。。
linux40
2015-10-11 18:14:15 +08:00
@htfy96 只不过没有第二行错误了
htfy96
2015-10-11 19:53:29 +08:00
@linux40 贴个在 gist 的完整代码吧……
linux40
2015-10-11 21:59:04 +08:00
@linux40 好了
htfy96
2015-10-12 18:28:10 +08:00
@linux40

第 106 ~ 109 行:

template <typename T1, typename T2>
struct tuple_helper<T1, T2> {
T1 t1;
T1 t2;

应该改成
template <typename T1, typename T2>
struct tuple_helper<T1, T2> {
T1 t1;
T2 t2;

就正常了。

原来的写法貌似编译器尝试隐式转换出了一个右值……
linux40
2015-10-12 19:49:27 +08:00
@htfy96 汗,原来是这里错了,感谢了啊。。。
linux40
2015-10-14 16:33:36 +08:00
@htfy96 现在我意识到了 tuple 用这么简单的写法是不行的,首先要保证参数最多只有一个类类型,其次当参数只有一个类类型,且那个类类型是 tuple 时,要保证正确的函数调用。。。
linux40
2015-10-14 16:36:28 +08:00
@htfy96 呃,不对,是我没加逗号。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/226321

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX