我想初始化一个静态的std::map
,其中的值是不可复制的。我将我的类(class)称为 ValueClass。 ValueClass 有一个 std::unique_ptr
作为私有(private)成员,我什至通过扩展如下所示的 non_copyable
来确保 ValueClass 不可复制:
class non_copyable {
public:
non_copyable() = default;
protected:
virtual ~non_copyable() = default;
private:
non_copyable(const non_copyable&) = delete;
non_copyable& operator=(const non_copyable&) = delete;
};
现在我尝试使用我的类作为值来定义一个 std::map:
static std::map<int, ValueClass> value_classes = {
{0, ValueClass()},
{1, ValueClass() }
};
initializer_list
尝试复制此类时出现编译错误。
整个周末我都尝试编写自己的 make_map
函数,在很多小时内启用初始化而不复制,但我失败了。我试过了 this , that和 other但它们都不能用 Visual Studio 15.9.4 编译。
如何使用 Visual Studio 编译器在不强制复制的情况下初始化静态 std::map,并且在一个函数中统一初始化?
编辑: 这是现实生活场景的简化版本,我正在努力使它正常工作(请原谅我缺乏命名约定和案例不一致):
#include <iostream>
#include <map>
class non_copyable {
public:
non_copyable() = default;
protected:
virtual ~non_copyable() = default;
private:
non_copyable(const non_copyable&) = delete;
non_copyable& operator=(const non_copyable&) = delete;
};
class InnerValueClass : public non_copyable
{
public:
InnerValueClass(const int inner_number) : inner_number_(inner_number) { }
private:
int inner_number_;
};
class ValueClass : public non_copyable
{
public:
ValueClass(const int number1) : number1_(number1) { }
ValueClass(const bool condition) : condition_(condition), inner_value_(
std::make_unique<InnerValueClass>(5)) { }
private:
int number1_{};
bool condition_{};
std::unique_ptr<InnerValueClass> inner_value_{};
};
/* Inline initialization of std::map copies, this is for initialization of non-copy types*/
template <typename TKey, typename TNonCopyableValue>
class make_map_by_moving
{
typedef std::map<TKey, TNonCopyableValue> map_type;
map_type map_;
public:
make_map_by_moving(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(key, std::move(val));
}
make_map_by_moving<TKey, TNonCopyableValue>& operator()(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(key, std::move(val));
return *this;
}
operator const map_type&()
{
return map_;
}
};
static std::map<int, ValueClass> map =
make_map_by_moving<int, ValueClass>
(1, ValueClass(5))
(2, ValueClass(true));
/* It goes on like this for hundreds of lines, so I really appreciate any
solution that leave me with a clean initialization rather than calling
functions on std::map */
int main() { }
重复编辑:该问题中提供的解决方案不适用于我拥有的类结构。我也在寻找修复 make_map_by_moving
函数的解决方案,换句话说就是内联初始化,答案是提供一个带有函数调用的命令式解决方案。
最佳答案
您不能直接执行此操作,因为 initializer_list
的所有元素都有 const
支持 - 并且必须将它们从初始化列表复制到容器中。显然,这需要复制。不幸的是,无法从初始化列表中放置。
在 C++17 中,由于有保证的复制省略,您可以这样做:
std::map<int, non_copyable> get() {
std::map<int, non_copyable> m;
m.emplace(std::piecewise_construct, std::tuple(0), std::tuple());
m.emplace(std::piecewise_construct, std::tuple(1), std::tuple());
return m;
}
std::map<int, non_copyable> value_classes = get();
此代码不对 non_copyable
执行任何复制。我们将构造放置在 map
内部,然后因为 get()
是纯右值,所以没有从 get()
复制/移动到值类
。 get()
中的 m
是对象value_classes
。
一个稍微偷偷摸摸的方法是为此滥用 try_emplace()
:
std::map<int, non_copyable> get() {
std::map<int, non_copyable> m;
m.try_emplace(0);
m.try_emplace(1);
return m;
}
try_emplace()
单独获取 key 类型(因此您可以只传递一个 int
),然后单独获取用于放置的值的参数,这使得完成此操作的方式更加简洁。
关于c++ - 在统一的内联初始化中使用不可复制的值初始化静态 std::map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53806687/