V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
linux40
V2EX  ›  C

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

  •  1
     
  •   linux40 · 2015-10-08 15:01:39 +08:00 · 1222 次点击
    这是一个创建于 3338 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 {//...};的问题。。。

    第 1 条附言  ·  2015-10-11 18:20:14 +08:00
    去掉了所有 constexpr 之后
    ```
    In instantiation of ‘ static T2& glgltinySTL::tuple_helper_get<1ul>::get_ref(glgltinySTL::tuple_helper<T1, T2>&) [with T1 = char; T2 = unsigned int]’:
    required from ‘ static 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&]’
    required from ‘ 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&]’
    required from here
    错误:用类型为‘ unsigned int ’的右值初始化类型为‘ unsigned int&’的非常量引用无效
    return t.t2;
    ^
    ```
    第 2 条附言  ·  2015-10-11 18:23:00 +08:00

    直接看这里,上面不用看。。。

    In instantiation of ‘ static T2& glgltinySTL::tuple_helper_get<1ul>::get_ref(glgltinySTL::tuple_helper<T1, T2>&) [with T1 = char; T2 = unsigned int]’:
    required from ‘ static 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&]’
    required from ‘ 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&]’
    required from here
    错误:用类型为‘ unsigned int ’的右值初始化类型为‘ unsigned int&’的非常量引用无效
    return t.t2;
    ^

    第 3 条附言  ·  2015-10-11 21:58:18 +08:00
    完整代码。。。
    11 条回复    2015-10-14 16:36:28 +08:00
    htfy96
        1
    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
        2
    htfy96  
       2015-10-08 15:27:21 +08:00
    你的那个 tuple 的构造函数不是 constexpr 函数,因而产生的 t 不是 constant expression ,所以 constexpr 函数不能正确处理关于 t 的引用
    linux40
        3
    linux40  
    OP
       2015-10-08 17:38:01 +08:00
    @htfy96 谢谢啦,等下我把 constexpr 去掉, tuple 不是 constexpr 的。。。
    linux40
        4
    linux40  
    OP
       2015-10-11 18:10:06 +08:00
    @htfy96 还是一样的错误。。。
    linux40
        5
    linux40  
    OP
       2015-10-11 18:14:15 +08:00
    @htfy96 只不过没有第二行错误了
    htfy96
        6
    htfy96  
       2015-10-11 19:53:29 +08:00
    @linux40 贴个在 gist 的完整代码吧……
    linux40
        7
    linux40  
    OP
       2015-10-11 21:59:04 +08:00
    @linux40 好了
    htfy96
        8
    htfy96  
       2015-10-12 18:28:10 +08:00   ❤️ 1
    @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
        9
    linux40  
    OP
       2015-10-12 19:49:27 +08:00
    @htfy96 汗,原来是这里错了,感谢了啊。。。
    linux40
        10
    linux40  
    OP
       2015-10-14 16:33:36 +08:00 via Android
    @htfy96 现在我意识到了 tuple 用这么简单的写法是不行的,首先要保证参数最多只有一个类类型,其次当参数只有一个类类型,且那个类类型是 tuple 时,要保证正确的函数调用。。。
    linux40
        11
    linux40  
    OP
       2015-10-14 16:36:28 +08:00 via Android
    @htfy96 呃,不对,是我没加逗号。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5620 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 06:43 · PVG 14:43 · LAX 22:43 · JFK 01:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.