【问题标题】:C++ template code generation Error: use of 'some_variable' before deduction of 'auto'C++模板代码生成错误:在扣除'auto'之前使用'some_variable'
【发布时间】:2019-05-08 01:55:05
【问题描述】:

我在使用此特定代码时遇到了一些问题。问题很可能与 指向存储在 tuple 中的类型为 Harry 的成员的指针以及带有 Harryvector 相关类型变量,因为所有其他更简单的变体都可以工作。

我在使用 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);
}

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

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

【问题讨论】:

    标签: c++17 variadic-templates template-meta-programming auto generic-lambda


    【解决方案1】:

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

    首先:我用 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&amp; a : a_vector),所以它的类型必须由编译器推断,在 lambda 函数内部捕获,在推断之前使用(decltype(a.*x))类型。

    不管怎样,问题的解决方法很简单:为了让 g++ 开心,明确定义。

    您知道aa_vector 的一个元素,它被定义为std::vector&lt;A&gt; const &amp;,所以您知道aA const &amp;

    所以,如果你写循环

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

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

    【讨论】:

      猜你喜欢
      • 2017-09-16
      • 1970-01-01
      • 2020-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-03
      • 2012-08-20
      • 2013-04-14
      相关资源
      最近更新 更多