以下代码
vector<ofstream> v;
v.emplace_back("file1.txt");
v.emplace_back("file2.txt");
for (int i = 0, ilen = v.size(); i < ilen; ++i)
v[i] << "Test" << i << endl;
在VS2013中编译正常,但在GCC中失败并显示不可读的消息。似乎VS2013的行为是正确的。
vector
变得足够大时,内容应移动到新的内存区域。虽然我在标准中找不到合适的地方,但却说明了这一点。有人可以引用它吗?
答案 0 :(得分:14)
如果你向下滚动到clang引发的end of the errors,你会看到这个:
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/basic_ios.h:66:23: note: copy constructor of 'basic_ios<char, std::char_traits<char> >' is implicitly deleted because base class 'std::ios_base' has an inaccessible copy constructor
这是gcc长长的错误列表中的对应行:
/usr/include/c++/4.8/bits/basic_ios.h:66:11: note: 'std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)' is implicitly deleted because the default definition would be ill-formed:
class basic_ios : public ios_base
这是因为libstdc ++缺少basic_ios
的移动构造函数,如状态页面上列出的here。
27.5 | Iostreams基类|部分|缺少
basic_ios
上的移动和交换操作。
和here's相关的bugzilla。如果使用libc ++,则代码为compiles with clang。
从错误报告中复制的一个更简单的例子,fails to compile:
#include <sstream>
#include <utility>
std::stringstream getss(){
std::stringstream q;
return std::move(q);
}
答案 1 :(得分:5)
解决问题:
template<typename T, typename...Args>
std::unique_ptr<T> make_unique(Args&&...args) {
return std::unique_ptr<T>( new T(std::forward<Args>(args)...) );
}
如果您不想输入ofstream
:
template<typename...Args>
std::unique_ptr<std::ofstream> make_up_ofstream(Args&&...args) {
return make_unique<std::ofstream>(std::forward<Args>(args)...);
}
给你:
std::vector<std::unique_ptr<std::ofstream>> v;
v.emplace_back(make_up_ofstream("file1.txt"));
v.emplace_back(make_up_ofstream("file2.txt"));
for (int i = 0, ilen = v.size(); i < ilen; ++i)
*(v[i]) << "Test" << i << endl;
非常接近,不是吗?
这使我想写make_up
来推断你要分配给它的unique_ptr
的类型:
// dense boilerplate, obsolete in C++1y:
template<unsigned...>struct indexes{typedef indexes type;};
template<unsigned Max,unsigned...Is>struct make_indexes:make_indexes<Max-1,Max-1,Is...>{};
template<unsigned...Is>struct make_indexes<0,Is...>:indexes<Is...>{};
template<unsigned Max>using make_indexes_t=typename make_indexes<Max>::type;
template<typename T>using type=T;
template<typename... Args>
struct up_maker {
std::tuple<Args...> args;
template<class T, class...Ds, unsigned...Is>
std::unique_ptr<T,Ds...> helper( indexes<Is...> ) && {
return std::unique_ptr<T,Ds...>( new T(std::forward<Args>( std::get<Is>(args) )...) );
}
template<class T, class...Ds>
operator type<std::unique_ptr<T,Ds...>>() && {
return std::move(*this).helper<T,Ds...>( make_indexes_t< sizeof...(Args) >{} );
}
explicit up_maker( Args&&... args_in ):args( std::forward<Args>(args_in)... ) {}
up_maker( up_maker const& ) = delete;
up_maker( up_maker && ) = default;
up_maker& operator=( up_maker const& ) = delete;
up_maker& operator=( up_maker && ) = default;
};
template<typename...Args>
up_maker<Args...> make_up( Args&&... args ) {
return up_maker<Args...>( std::forward<Args>(args)... );
}
如果我写得正确的话,在代码中删除更多的样板:
std::vector<std::unique_ptr<std::ofstream>> v;
v.emplace_back(make_up("file1.txt"));
v.emplace_back(make_up("file2.txt"));
for (int i = 0, ilen = v.size(); i < ilen; ++i)
(*v[i]) << "Test" << i << std::endl;
...很多代码只是为了摆脱两个_ofstream
,但这很有趣。