【发布时间】:2016-02-05 17:40:35
【问题描述】:
我观察到以下代码的一个相当奇怪的行为:
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/any_range.hpp>
#include <vector>
#include <string>
#include <iostream>
#include "gsl.h"
template <typename T>
using ImmutableValueRange = boost::any_range<T, boost::bidirectional_traversal_tag, /*const*/ T>;
template <typename T, typename C>
ImmutableValueRange<T> make_transforming_immutable_range(const C& container)
{
return container | boost::adaptors::transformed([](const typename C::value_type& v) -> T
{
//std::cout << "trans : " << T{ v }.data() << "\n";
return T{ v };
});
}
void f(ImmutableValueRange<gsl::cstring_span<>> r)
{
for (const auto& c : r) {
std::cout << c.data() << "\n";
}
}
int main()
{
std::vector<std::string> v({ "x", "y", "z" });
f(make_transforming_immutable_range<gsl::cstring_span<>>(v));
}
这里的想法是隔离在any_range和gsl::string_span后面的函数f作为参数接收的字符串序列的实际表示(注意,提交将string_view更改为@987654326 @ 已在几个小时前向 GSL 制作)。
我的原始代码没有const T 作为Reference 模板参数any_range(它是一个简单的T),它在执行过程中崩溃。但是,这仅在发布模式下发生,在 Debug 或 RelWithDebInfo(由 CMake 生成)中运行良好。我使用了 VS2013/2015 x64。此外,尝试调试完整的 Release 版本,将调试输出添加到转换 lambda 消除了崩溃(我的猜测是它阻止了一些内联)。我的最终工作解决方案是将const T 指定为Reference。
但是,我仍然想知道为什么首先会发生崩溃?它是VS编译器错误吗? string_span 的当前实现中的错误?还是我只是滥用boost::any_range?
编辑
刚刚使用 clang 3.7.0 构建了版本并且行为相似(在调试中工作正常并且不会崩溃,但是在没有 const T 和 -O2 的情况下输出垃圾)。所以看起来不像是编译器的问题。
【问题讨论】:
-
祝你调试成功。您是否尝试调试它?您可以在发布模式下进行调试。
-
@WarrenP 当然。但它在 Debug/RelWithDebInfo 模式下工作得非常好,甚至在发布模式下的 lambda 中有一些调试输出,这让调试变得非常困难:)
标签: c++ c++11 boost cpp-core-guidelines string-span