这个问题建立在这个@FredOverflow 的问题之上。
澄清:
initializer_list
方法是必需的,因为VC++2012 有一个错误,可以防止命名空间参数的转发扩展。_MSC_VER <= 1700
有错误。
我编写了一个可变参数模板函数,它可以折叠类型化容器中的任意数量的参数。我使用类型的构造函数将可变参数转换为可使用的值。例如_variant_t
:)
在一次将参数推送到准备好的语句时,我的MySql
C++ 库需要这个,而我MySqlVariant
将输入数据转换为MYSQL_BIND
s。因为我可能使用s,所以当我可以使用大型容器BLOB
时,我想尽可能避免复制构造。move&&
initialize_list
我已经做了一个简单的测试,并注意到copy-construct
存储的元素会在超出范围时销毁它们。完美...然后我尝试将数据移出,令我initializer_list
惊讶的是,它与.lvalues
rvalues
std::move
有趣的是,这发生在Going Native 2013明确警告我移动不动,前进不前进......就像水一样,我的朋友- 留在思想的深处。
但这并没有阻止我 :)我决定价值观并仍然const_cast
将initializer_list
它们移出。需要执行驱逐令。这是我的实现:
template <typename Output_t, typename ...Input_t>
inline Output_t& Compact(Output_t& aOutput, Input_t&& ...aInput){
// should I do this? makes sense...
if(!sizeof...(aInput)){
return aOutput;
}
// I like typedefs as they shorten the code :)
typedef Output_t::value_type Type_t;
// can be either lvalues or rvalues in the initializer_list when it's populated.
std::initializer_list<Type_t> vInput = { std::forward<Input_t>(aInput)... };
// now move the initializer_list into the vector.
aOutput.reserve(aOutput.size() + vInput.size());
for(auto vIter(vInput.begin()), vEnd(vInput.end()); vIter != vEnd; ++vIter){
// move (don't copy) out the lvalue or rvalue out of the initializer_list.
// aOutput.emplace_back(std::move(const_cast<Type_t&>(*vIter))); // <- BAD!
// the answer points out that the above is undefined so, use the below
aOutput.emplace_back(*vIter); // <- THIS is STANDARD LEGAL (copy ctor)!
}
// done! :)
return aOutput;
}
使用它很容易:
// You need to pre-declare the container as you could use a vector or a list...
// as long as .emplace_back is on duty!
std::vector<MySqlVariant> vParams;
Compact(vParams, 1, 1.5, 1.6F, "string", L"wstring",
std::move(aBlob), aSystemTime); // MySql params :)
我还在 IDEone 上上传了一个完整的测试 ^,它显示为std::string
使用此功能正确移动的内存。(我会把它全部粘贴在这里,但它有点长......)
只要_variant_t
(或任何最终包装对象)具有正确的构造函数,那就太好了。如果数据可以移出,那就更好了。当我测试它并且事情朝着正确的方向发展时,它几乎可以工作std::move
:)
我的问题很简单:
- 我在标准方面做得对吗?
- 它工作正常的事实是有意的还是只是副作用?
- 如果
std::move
默认情况下不起作用initializer_list
,那么我在这里做什么:非法,不道德,hacky ......还是完全错误?
PS:我是一名自学成才的Windows Native C++
开发人员,对标准一无所知。
^ 如果我在这里做非常不标准的事情,我的借口。
更新
谢谢大家,我现在既有答案也有解决方案(一个短的和长的)。
我喜欢 SO 的 C++11 方面。 这里有很多知识渊博的人...