C++ template code generation Error: use of 'some_variable' before deduction of 'auto'
C++ template code generation Error: use of 'some_variable' before deduction of 'auto'
我 运行 遇到了这个特定代码的一些问题。该问题很可能与存储在 元组 中的 指向 Harry
类型成员的指针和 vector with Harry
type 变量,因为所有其他更简单的变体都可以工作。
我用 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);
}
如果有人能提供一些解决此问题的提示,那就太好了。
(我知道这一切看起来毫无意义,为什么有人需要这样做。但是,我的首要任务不是编写好的、可用的代码,而是学习东西,而且我真的很想让我想到的这个架构工作。)
It would be very nice if someone had some tips on how to solve this.
首先:我用 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
的一个元素,定义为 std::vector<A> const &
,因此您知道 a
是 A const &
。
因此,如果您编写循环
for ( A const & a : a_vector )
{
// ....
}
不再需要推断 a
的类型,您的代码也可以使用 g++ 进行编译。
我 运行 遇到了这个特定代码的一些问题。该问题很可能与存储在 元组 中的 指向 Harry
类型成员的指针和 vector with Harry
type 变量,因为所有其他更简单的变体都可以工作。
我用 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);
}
如果有人能提供一些解决此问题的提示,那就太好了。
(我知道这一切看起来毫无意义,为什么有人需要这样做。但是,我的首要任务不是编写好的、可用的代码,而是学习东西,而且我真的很想让我想到的这个架构工作。)
It would be very nice if someone had some tips on how to solve this.
首先:我用 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
的一个元素,定义为 std::vector<A> const &
,因此您知道 a
是 A const &
。
因此,如果您编写循环
for ( A const & a : a_vector )
{
// ....
}
不再需要推断 a
的类型,您的代码也可以使用 g++ 进行编译。