如何隐式调用 shared_ptr 中包装的值的构造函数,该值位于 std::map 集合中
How to call implicitly constructor of value wrapped in shared_ptr which is placed in std::map collection
我正在使用代码生成器,我无法直接获取包装在 shared_ptr
中并放置在 std::map
.
中的值的类名
我遇到了这样一种情况,我需要创建新的地图对象,但无法访问类名,我无法执行有效的对象构造函数调用。我尝试使用映射运算符 at[],它调用值构造函数,但它调用 shared_ptr<T>
构造函数并且内部对象保持未初始化状态。
这里是例子:
#include <iostream>
#include <map>
#include <memory>
class A
{
public:
A() { std::cout << "A"; }
int getMember() const { return m_member; }
private:
int m_member = 1;
};
int main()
{
std::map<int, A> mapIntToA;
std::map<int, std::shared_ptr<A>> mapIntToAptr;
mapIntToA[1]; // runs A constructor
std::cout << mapIntToA[1].getMember();
mapIntToAptr[1]; // runs shared_ptr constructor
// cant call methods of uninitalized object
// std::cout << mapIntToAptr[1]->getMember();
// this init works, but I can't use classname 'A' in my code generator
// mapIntToAptr[1] = std::make_shared<A>();
return 0;
}
您可以使用 std::map
和 std::shared_ptr
的成员类型来获取元素的类型。
类似
using type = typename std::map<int, std::shared_ptr<A>>::mapped_type::element_type;
mapIntToAptr[1] = std::make_shared<type>();
mapIntToAptr.emplace(1, ::std::make_shared<decltype(mapIntToAptr)::mapped_type::element_type>());
请注意,使用 emplace
可以防止在 make_shared
抛出时 map 留下 nullptr 值的情况。
operator[]
of std::map
默认构造缺少值。
因此,您可以将 std::shared_ptr
包装到一个 class 中,它会按预期构造您的内部 class,例如:
template <typename T>
struct shared_ptr_wrapper
{
std::shared_ptr<T> data = std::make_shared<T>();
operator const std::shared_ptr<T>& () const {return data;}
operator std::shared_ptr<T>& () {return data;}
const std::shared_ptr<T>& operator ->() const { return data; }
std::shared_ptr<T>& operator ->() {return data;}
const T& operator *() const { return *data; }
T& operator *() {return *data;}
};
然后
std::map<int, shared_ptr_wrapper<A>> mapIntToAptr;
mapIntToAptr[1]; // runs shared_ptr constructor
std::cout << mapIntToAptr[1]->getMember(); // Ok
我正在使用代码生成器,我无法直接获取包装在 shared_ptr
中并放置在 std::map
.
我遇到了这样一种情况,我需要创建新的地图对象,但无法访问类名,我无法执行有效的对象构造函数调用。我尝试使用映射运算符 at[],它调用值构造函数,但它调用 shared_ptr<T>
构造函数并且内部对象保持未初始化状态。
这里是例子:
#include <iostream>
#include <map>
#include <memory>
class A
{
public:
A() { std::cout << "A"; }
int getMember() const { return m_member; }
private:
int m_member = 1;
};
int main()
{
std::map<int, A> mapIntToA;
std::map<int, std::shared_ptr<A>> mapIntToAptr;
mapIntToA[1]; // runs A constructor
std::cout << mapIntToA[1].getMember();
mapIntToAptr[1]; // runs shared_ptr constructor
// cant call methods of uninitalized object
// std::cout << mapIntToAptr[1]->getMember();
// this init works, but I can't use classname 'A' in my code generator
// mapIntToAptr[1] = std::make_shared<A>();
return 0;
}
您可以使用 std::map
和 std::shared_ptr
的成员类型来获取元素的类型。
类似
using type = typename std::map<int, std::shared_ptr<A>>::mapped_type::element_type;
mapIntToAptr[1] = std::make_shared<type>();
mapIntToAptr.emplace(1, ::std::make_shared<decltype(mapIntToAptr)::mapped_type::element_type>());
请注意,使用 emplace
可以防止在 make_shared
抛出时 map 留下 nullptr 值的情况。
operator[]
of std::map
默认构造缺少值。
因此,您可以将 std::shared_ptr
包装到一个 class 中,它会按预期构造您的内部 class,例如:
template <typename T>
struct shared_ptr_wrapper
{
std::shared_ptr<T> data = std::make_shared<T>();
operator const std::shared_ptr<T>& () const {return data;}
operator std::shared_ptr<T>& () {return data;}
const std::shared_ptr<T>& operator ->() const { return data; }
std::shared_ptr<T>& operator ->() {return data;}
const T& operator *() const { return *data; }
T& operator *() {return *data;}
};
然后
std::map<int, shared_ptr_wrapper<A>> mapIntToAptr;
mapIntToAptr[1]; // runs shared_ptr constructor
std::cout << mapIntToAptr[1]->getMember(); // Ok