代码之家  ›  专栏  ›  技术社区  ›  Darius Duesentrieb

C++模板代码生成错误:在“Auto'”扣除前使用“变量变量”

  •  0
  • Darius Duesentrieb  · 技术社区  · 6 年前

    我遇到了这个特定代码的一些问题这个问题很可能与 指向类型为的成员的指针 Harry 存储在 元组 ,和 矢量 具有 哈利 类型变量,因为所有其他更简单的变量都可以工作。

    我用g++得到的错误是:


    main.cpp: In instantiation of 'abra(const std::vector<A>&, const std::tuple<_Elements ...>&) [with A = Harry; B = {int Harry::*, int* Harry::*}]::<lambda(const auto:1&)> [with auto:1 = int Harry::*]':
    
    main.cpp:10:13:   required from 'void tuple_foreach_constexpr(const std::tuple<T ...>&, F) [with long unsigned int i = 0; long unsigned int size = 2; F = abra(const std::vector<A>&, const std::tuple<_Elements ...>&) [with A = Harry; B = {int Harry::*, int* Harry::*}]::<lambda(const auto:1&)>; T = {int Harry::*, int* Harry::*}]'
    
    main.cpp:17:82:   required from 'void tuple_foreach_constexpr(const std::tuple<_Elements ...>&, F) [with F = abra(const std::vector<A>&, const std::tuple<_Elements ...>&) [with A = Harry; B = {int Harry::*, int* Harry::*}]::<lambda(const auto:1&)>; T = {int Harry::*, int* Harry::*}]'
    
    main.cpp:29:32:   required from 'void abra(const std::vector<A>&, const std::tuple<_Elements ...>&) [with A = Harry; B = {int Harry::*, int* Harry::*}]'
    
    main.cpp:56:27:   required from here
    
    main.cpp:31:82: error: use of 'a' before deduction of 'auto'
    
                 if constexpr(std::is_pointer<typename std::remove_reference<decltype(a.*x)>::type>::value)
    
                                                                                      ^
    
    main.cpp:33:30: error: invalid type argument of unary '*' (have 'int')
    
                     std::cout << *(a.*x) << std::endl;
    
                                  ^~~~~~~
    
    main.cpp:6:6: error: 'void tuple_foreach_constexpr(const std::tuple<T ...>&, F) [with long unsigned int i = 1; long unsigned int size = 2; F = abra(const std::vector<A>&, const std::tuple<_Elements ...>&) [with A = Harry; B = {int Harry::*, int* Harry::*}]::<lambda(const auto:1&)>; T = {int Harry::*, int* Harry::*}]', declared using local type 'abra(const std::vector<A>&, const std::tuple<_Elements ...>&) [with A = Harry; B = {int Harry::*, int* Harry::*}]::<lambda(const auto:1&)>', is used but never defined [-fpermissive]
    
     void tuple_foreach_constexpr(const std::tuple<T...>& tuple, F func)
    
          ^~~~~~~~~~~~~~~~~~~~~~~
    

    代码:

    #include <iostream>
    #include <tuple>
    #include <vector>
    
    template<size_t i, size_t size, typename F, typename... T>
    void tuple_foreach_constexpr(const std::tuple<T...>& tuple, F func)
    {
        if constexpr(i<size)
        {
            func(std::get<i>(tuple));
            tuple_foreach_constexpr<i+1, size, F, T...>(tuple, func);
        }
    }
    template<typename F, typename... T>
    void tuple_foreach_constexpr(const std::tuple<T...>& tuple, F func)
    {
        tuple_foreach_constexpr<0, std::tuple_size<std::tuple<T...>>::value, F, T...>(tuple, func);
    }
    
    template<typename A, typename... B>
    void abra
    (
        const std::vector<A>& a_vector,
        const std::tuple<B...>& b_tuple
    )
    {
        for(const auto& a : a_vector)
        {
            tuple_foreach_constexpr(b_tuple, [&a](const auto &x)
            {
                if constexpr(std::is_pointer<typename std::remove_reference<decltype(a.*x)>::type>::value)
                {
                    std::cout << *(a.*x) << std::endl;
                }
                else
                {
                    std::cout << a.*x << std::endl;
                } // this does NOT work
    
                //std::cout << a.*x << std::endl; // this does work
            });
        }
    }
    
    struct Harry
    {
        int a;
        int* b;
    };    
    
    int main()
    {
        int m = 20;
        std::vector<Harry> h_vector = {Harry{10, &m}};
        std::tuple t_tuple = std::make_tuple(&Harry::a, &Harry::b);
    
        abra(h_vector, t_tuple);
    }
    

    如果有人能提供一些解决这个问题的技巧,那就太好了。

    (我知道这一切看起来都没有道理,为什么会有人需要这样做。然而,我的首要任务不是编写好的、可用的代码,而是学习一些东西,而且我真的很想得到我想工作的这个架构。)

    0 回复  |  直到 6 年前
        1
  •  2
  •   max66    6 年前

    如果有人能提供一些解决这个问题的技巧,那就太好了。

    首先:我用g++再现了你的错误,但是我的clang++(7.0.1)编译你的代码没有问题。

    谁是对的g++还是clang++?

    我不是语言律师,我也不确定,但我怀疑这是一个g++错误。

    g++是什么意思?

    就是说在这个循环中

    for(const auto& a : a_vector)
    {
        tuple_foreach_constexpr(b_tuple, [&a](const auto &x)
        {
            if constexpr(std::is_pointer<typename std::remove_reference<decltype(a.*x)>::type>::value)
            {
                std::cout << *(a.*x) << std::endl;
            }
            else
            {
                std::cout << a.*x << std::endl;
            } // this does NOT work
    
            //std::cout << a.*x << std::endl; // this does work
        });
    }
    

    这个 a 变量,这是 auto 变量( const auto& a : a_vector )所以它的类型必须由编译器推导出来,这是在lambda函数中捕获的( decltype(a.*x) )在类型的演绎之前。

    无论如何,问题的解决方法很简单:为了让g++高兴,显式地定义它。

    你知道的 a_vector 定义为 std::vector<A> const & ,所以你知道 是一个 A const & .

    所以,如果你写循环

    for ( A const & a : a_vector )
     {
       // ....
     }
    

    不需要再推断 你的代码也用g++编译。