【问题标题】:Insert templated class in std::map with construction at insertion在 std::map 中插入模板类,并在插入时构造
【发布时间】:2017-09-01 15:21:33
【问题描述】:

我正在尝试将没有复制构造函数的模板化类的实例插入到地图中。下面的代码不起作用,因为在emplace 函数中编译器想要调用复制构造函数。我不明白为什么,因为我从C++ reference 了解到 emplace 不会移动或复制:

小心使用 emplace 允许在构造新元素的同时 避免不必要的复制或移动操作。

这是我的代码:

#include <map>
#include <string>

template<typename T> class Class_a
{
    public:
        Class_a(T t1, T t2) : t1_(t1), t2_(t2) {}
        ~Class_a() {}
        Class_a(const Class_a&) = delete;
        Class_a& operator=(const Class_a&) = delete;
        Class_a(Class_a&&) = delete;
    private:
        const T t1_;
        const T t2_;
};

template<typename T>
using Class_a_map = std::map<std::string, Class_a<T>>;

int main()
{
    Class_a_map<double> class_a_map;
    std::string name = "test";
    double number1 = 42;
    double number2 = 43;
    class_a_map.emplace(name, Class_a<double>(number1, number2));

    return 0;
}

【问题讨论】:

  • 为什么要让类不可移动?如果它是可移动但不可复制的,这将很好。

标签: c++ c++11 templates dictionary std


【解决方案1】:

您可以使用std::piecewise_constructstd::forward_as_tuple 就地创建对象。

class_a_map.emplace(
    std::piecewise_construct, 
    std::forward_as_tuple(name),
    std::forward_as_tuple(number1, number2)
);

live wandbox example


std::map::emplace 完美地将一堆参数转发给用于键/值存储的底层std::pairstd::pair::pair 有一个重载,它以 std::piecewise_construct_t 作为其第一个参数,然后是两个 std::tuple 实例:第一个将用于构造 .first,第二个将用于构造 .second地点。

来自 cppreference,关于std::pair 的分段构造函数:

first_args的元素转发给first的构造函数,并将second_args的元素转发给second的构造函数。这是唯一可用于创建一对不可复制、不可移动类型的非默认构造函数。

【讨论】:

  • 在这种特殊情况下,tie 更短。
猜你喜欢
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 2010-09-10
  • 2019-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多