我创建了一个方便构建lambda函数的宏,使用它我可以迭代我编写的库中的张量对象。但是,嵌套这些宏似乎会导致GCC经历内部分段错误。在扩展编译器的预处理器输出并经历一些试验和错误之后,我发现原因似乎是在类或结构的方法中声明的嵌套lambda函数的参数列表中使用decltype
。下面是使用标准库的最小示例。
#include <iostream>
#include <type_traits>
template <class Iterator, class Func>
void for_each(const Iterator first, const Iterator last, Func func)
{
for (Iterator it = first; it != last; ++it) {
func(*it);
}
}
template <class T>
class helper
{
typedef typename T::size_type type;
};
template <class T>
class helper<T&>
{
typedef typename T::size_type type;
};
template <class T>
class helper<T*>
{
typedef typename T::size_type type;
};
struct bar
{
struct foo
{
typedef int size_type;
} foo_;
void test()
{
int arr[] = { 1, 2, 3 };
for_each(arr, arr + 3, [&](int i) {
/*
** XXX: The "typename ... type" segfaults g++!
*/
for_each(arr, arr + 3, [&](typename helper<decltype(foo_)>::type j) {
});
});
}
};
int main()
{
return 0;
}
$ g++ -Wall -std=c++0x nested_lambda.cpp
nested_lambda.cpp: In lambda function:
nested_lambda.cpp:42:56: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-4.6/README.Bugs> for instructions.
Preprocessed source stored into /tmp/ccqYohFA.out file, please attach this to your bugreport.
我最初选择使用decltype
,因为对象被传递给宏,我需要提取对象的类型。从对象的类型(T
,T&
或T*
)开始,我会使用特征类来提取T::size_type.
size_type
然后是类型lambda函数参数。
如何在不必使用typedef提前声明lambda函数参数的类型的情况下绕过这个问题?如果你能想到一些其他可以在宏中轻松实现的解决方案(即在lambda函数的参数列表中重复复制和粘贴),那也可以。
答案 0 :(得分:1)
对于那些可能遇到类似问题的人来说,这是一个非常粗略的解决方法,我可以提出的最佳标准解决方案是让宏提前声明一个typedef,连接类似GUID的前缀(我个人推荐_qki_zbeu26_w92b27bqy_r62zf91j2n_s0a02_
)和__LINE__
为typedef名称生成一些混乱的废话。幸运的是,这个名字不会与任何其他定义冲突。
为了确保即使将warble名称用于lambda函数参数类型也会连接相同的__LINE__
,需要通过最初传递宏参数的宏生成warbled name,如下面的代码示例。
#define _foo_GUID \
_qki_zbeu26_w92b27bqy_r62zf91j2n_s0a02_
#define _foo_MANGLE_IMPL2(a, b) \
a ## b
#define _foo_MANGLE_IMPL(a, b) \
_foo_MANGLE_IMPL2(a, b)
#define _foo_MANGLE(a) \
_foo_MANGLE_IMPL(_foo_GUID, a)
将_foo_MANGLE(__LINE__)
作为宏参数传递时,请确保存在额外的间接级别,以便_foo_MANGLE(__LINE__)
在使用之前进行评估。
答案 1 :(得分:0)
此错误目前为addressed,我认为应尽快修复。