2

我遇到了这个特定代码的一些问题。该问题很可能与指向Harry存储在tuple中的类型成员的指针以及具有类型变量的向量有关,因为所有其他更简单的变体都可以工作。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);
}

如果有人对如何解决这个问题有一些提示,那就太好了。

(我知道这一切看起来毫无意义,为什么有人需要这样做。但是,我的首要任务不是编写好的、可用的代码,而是学习东西,而且我真的想让我想到的这个架构工作.)

4

1 回答 1

2

如果有人对如何解决这个问题有一些提示,那就太好了。

首先:我用 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是一个a_vector被定义为a的元素std::vector<A> const &,所以你知道那a是a A const &

所以,如果你写循环

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

不再需要推断类型,a并且您的代码也可以使用 g++ 编译。

于 2019-05-08T08:22:51.693 回答