C++ 如何在只有受保护或私有构造函数的类上调用::std::make_shared?
我有一个不起作用的代码,但我认为其意图是明确的: testmakeshared.cppC++ 如何在只有受保护或私有构造函数的类上调用::std::make_shared?,c++,c++11,shared-ptr,C++,C++11,Shared Ptr,我有一个不起作用的代码,但我认为其意图是明确的: testmakeshared.cpp #包括 甲级{ 公众: static::std::shared_ptr create(){ return::std::make_shared(); } 受保护的: A(){} A(常数A&)=删除; 常量A&运算符=(常量A&)=删除; }; ::std::shared_ptr foo() { 返回A::create(); } 但我在编译时遇到了这个错误: g++ -std=c++0x -march=nat
#包括
甲级{
公众:
static::std::shared_ptr create(){
return::std::make_shared();
}
受保护的:
A(){}
A(常数A&)=删除;
常量A&运算符=(常量A&)=删除;
};
::std::shared_ptr foo()
{
返回A::create();
}
但我在编译时遇到了这个错误:
g++ -std=c++0x -march=native -mtune=native -O3 -Wall testmakeshared.cpp
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr.h:52:0,
from /usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/memory:86,
from testmakeshared.cpp:1:
testmakeshared.cpp: In constructor ‘std::_Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp>::_Sp_counted_ptr_inplace(_Alloc) [with _Tp = A, _Alloc = std::allocator<A>, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]’:
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr_base.h:518:8: instantiated from ‘std::__shared_count<_Lp>::__shared_count(std::_Sp_make_shared_tag, _Tp*, const _Alloc&, _Args&& ...) [with _Tp = A, _Alloc = std::allocator<A>, _Args = {}, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr_base.h:986:35: instantiated from ‘std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = std::allocator<A>, _Args = {}, _Tp = A, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr.h:313:64: instantiated from ‘std::shared_ptr<_Tp>::shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = std::allocator<A>, _Args = {}, _Tp = A]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr.h:531:39: instantiated from ‘std::shared_ptr<_Tp> std::allocate_shared(const _Alloc&, _Args&& ...) [with _Tp = A, _Alloc = std::allocator<A>, _Args = {}]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr.h:547:42: instantiated from ‘std::shared_ptr<_Tp1> std::make_shared(_Args&& ...) [with _Tp = A, _Args = {}]’
testmakeshared.cpp:6:40: instantiated from here
testmakeshared.cpp:10:8: error: ‘A::A()’ is protected
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr_base.h:400:2: error: within this context
Compilation exited abnormally with code 1 at Tue Nov 15 07:32:58
g++-std=c++0x-march=native-mtune=native-O3-Wall testmakeshared.cpp
在/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../../../../include/c++/4.6.1/bits/shared_ptr.h:52:0中包含的文件中,
从/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../../../../../include/c++/4.6.1/memory:86,
来自testmakeshared.cpp:1:
testmakeshared.cpp:在构造函数的std::_Sp_counted_ptr_inplace::_Sp_counted_ptr_inplace(_Alloc)[带_Tp=A,_Alloc=std::分配器,u gnu_cxx::_Lock_policy _Lp=(u gnu cxx:_Lock_policy)2u]:
/4.6.1/比特/共享的(4.6.1)1/4.6.1/比特/共享的(4.6.1)比特/共享的(4.6.1)比特/共享的(4.6.6.1)公共卫生:518:8:8:从“std”中实例化的:从“std::::::::(U/c/c/c/c/c/c/c/c/c/c/c/8:8:8:8:8:8:8:从”从“std”中,从从“std::::::::::::::,从“std::::::::::,从”中获得的)中获得的)的,从”中的,公共公共服务:,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,_政策)2u]'
/4.6.1/4.6.1/7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,/4.6.6.1.1/比特/比特/比特/比特/比特/比特/共享的(1.6.1/4.1/4.1/4.1/比特/比特/比特/共享的/比特/共享的(1.1.6.1/比特/比特/比特/共享的)共享的。基础。h:986:986:35:35:35:35:从以下:从:从从“std::::::::::::::::::::::::::::::::::::::::,从”从”从”从“std”的从“std/从“std::::,从”中的”的”从“std::::::::::/(2)2u]'
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../../../../include/c++/4.6.1/bits/shared_ptr.h:313:64:从“std::shared_ptr::shared_ptr(std:_Sp_make_shared_标签、const_Alloc&、_Args&&&……[with_Alloc=std::分配器、_Args={}、_Tp=A]”实例化
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../../../../../../include/c++/4.6.1/bits/shared_ptr.h:531:39:从“std::shared_ptr std::allocate_shared(const_Alloc&,_Args&&…[带_Tp=A,_Alloc=std::allocator,_Args={}”)实例化
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../../../../../include/c++/4.6.1/bits/shared_ptr.h:547:42:从“std::shared_ptr std::make_shared(_Args&&…[带_Tp=A,_Args={})”实例化
testmakeshared.cpp:6:40:从此处实例化
testmakeshared.cpp:10:8:错误:“A::A()”受保护
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../../../../include/c++/4.6.1/bits/shared_ptr_base.h:400:2:错误:在此上下文中
编译在11月15日星期二07:32:58异常退出,代码为1
这条消息基本上是说,模板实例化堆栈中从::std::make_shared
向下的一些随机方法无法访问构造函数,因为它受到保护
但我真的想同时使用::std::make_shared
,并防止任何人生成此类对象,而该对象不是::std::shared_ptr
。有什么办法可以做到这一点吗?这个怎么样
static std::shared_ptr<A> create()
{
std::shared_ptr<A> pA(new A());
return pA;
}
static std::shared_ptr create()
{
std::shared_ptr pA(新的A());
返回pA;
}
查看20.7.2.2.6共享ptr创建[util.smartptr.shared.create]第1段中的std::make_shared
要求:表达式::new(pv)T(std::forward(args)…
,其中pv
具有类型void*
,并指向适合容纳T
类型对象的存储区,应格式良好<代码>A应为分配器(17.6.3.5)。A
的复制构造函数和析构函数不应引发异常
由于需求是在表达式中无条件地指定的,并且没有考虑范围之类的因素,所以我认为友谊之类的技巧是正确的
一个简单的解决方案是从A
派生。这不需要使A
成为接口,甚至不需要多态类型
// interface in header
std::shared_ptr<A> make_a();
// implementation in source
namespace {
struct concrete_A: public A {};
} // namespace
std::shared_ptr<A>
make_a()
{
return std::make_shared<concrete_A>();
}
//头中的接口
std::shared_ptr make_a();
//源代码中的实现
名称空间{
结构混凝土A:公共A{};
}//名称空间
std::共享的ptr
使成为
{
返回std::make_shared();
}
可能更好,我可能会接受。但我也提出了一个更丑陋的方法,但仍然让所有内容都是内联的,不需要派生类:
#include <memory>
#include <string>
class A {
protected:
struct this_is_private;
public:
explicit A(const this_is_private &) {}
A(const this_is_private &, ::std::string, int) {}
template <typename... T>
static ::std::shared_ptr<A> create(T &&...args) {
return ::std::make_shared<A>(this_is_private{0},
::std::forward<T>(args)...);
}
protected:
struct this_is_private {
explicit this_is_private(int) {}
};
A(const A &) = delete;
const A &operator =(const A &) = delete;
};
::std::shared_ptr<A> foo()
{
return A::create();
}
::std::shared_ptr<A> bar()
{
return A::create("George", 5);
}
::std::shared_ptr<A> errors()
{
::std::shared_ptr<A> retval;
// Each of these assignments to retval properly generates errors.
retval = A::create("George");
retval = new A(A::this_is_private{0});
return ::std::move(retval);
}
#包括
#包括
甲级{
受保护的:
该结构是私有的;
公众:
显式A(const this_是_private&){
A(const this_is_private&,::std::string,int){}
模板
static::std::shared_ptr create(T&&…args){
return::std::make_shared(这个_是_private{0}),
::std::转发(args);
}
受保护的:
此结构是私有的{
显式此_是_private(int){}
};
A(常数A&)=删除;
常量A&运算符=(常量A&)=删除;
};
::std::shared_ptr foo()
{
返回A::create();
}
::std::共享_ptr bar()
{
返回A::create(“George”,5);
}
::std::共享的ptr错误()
{
::std::共享检索;
//每个要返回的赋值都会正确生成错误。
retval=A::创建(“乔治”);
retval=newa(A::this_is_private{0});
return::std::move(retval);
}
编辑2017-01-06:我更改了此选项,以明确此想法可明确且简单地扩展到采用论点的构造函数,因为其他人按照这些思路提供答案,似乎对此感到困惑。因为我不喜欢已经提供的答案,我决定搜索并找到解决方案这并不像前面的答案那样笼统,但我更喜欢它(tm)。回想起来,它并不比Omnifarius提供的好多少,但可能还有其他人也喜欢它:) 这不是我发明的,而是Jonathan Wakely(GCC开发者)的想法 不幸的是,确实如此
#include <memory>
#include <string>
class A {
protected:
struct this_is_private;
public:
explicit A(const this_is_private &) {}
A(const this_is_private &, ::std::string, int) {}
template <typename... T>
static ::std::shared_ptr<A> create(T &&...args) {
return ::std::make_shared<A>(this_is_private{0},
::std::forward<T>(args)...);
}
protected:
struct this_is_private {
explicit this_is_private(int) {}
};
A(const A &) = delete;
const A &operator =(const A &) = delete;
};
::std::shared_ptr<A> foo()
{
return A::create();
}
::std::shared_ptr<A> bar()
{
return A::create("George", 5);
}
::std::shared_ptr<A> errors()
{
::std::shared_ptr<A> retval;
// Each of these assignments to retval properly generates errors.
retval = A::create("George");
retval = new A(A::this_is_private{0});
return ::std::move(retval);
}
#include <memory>
template<typename Private>
struct MyAlloc : std::allocator<Private>
{
void construct(void* p) { ::new(p) Private(); }
};
class A {
public:
static ::std::shared_ptr<A> create() {
return ::std::allocate_shared<A>(MyAlloc<A>());
}
protected:
A() {}
A(const A &) = delete;
const A &operator =(const A &) = delete;
friend struct MyAlloc<A>;
};
int main() {
auto p = A::create();
return 0;
}
#include <memory>
template<typename T>
class safe_enable_shared_from_this : public std::enable_shared_from_this<T>
{
public:
template<typename... _Args>
static ::std::shared_ptr<T> create(_Args&&... p_args) {
return ::std::allocate_shared<T>(Alloc(), std::forward<_Args>(p_args)...);
}
protected:
struct Alloc : std::allocator<T>
{
template<typename _Up, typename... _Args>
void construct(_Up* __p, _Args&&... __args)
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
};
safe_enable_shared_from_this(const safe_enable_shared_from_this&) = delete;
safe_enable_shared_from_this& operator=(const safe_enable_shared_from_this&) = delete;
};
class A : public safe_enable_shared_from_this<A> {
private:
A() {}
friend struct safe_enable_shared_from_this<A>::Alloc;
};
class B : public safe_enable_shared_from_this<B> {
private:
B(int v) {}
friend struct safe_enable_shared_from_this<B>::Alloc;
};
int main() {
auto a = A::create();
auto b = B::create(5);
return 0;
}
class B
{
public:
// B your methods...
private:
B();
friend class A;
};
class B
{
public:
class Pass
{
Pass() {}
friend class A;
};
B(Pass, int someArgument)
{
}
};
class A
{
public:
A()
{
// This is valid
auto ptr = std::make_shared<B>(B::Pass(), 42);
}
};
class C
{
public:
C()
{
// This is not
auto ptr = std::make_shared<B>(B::Pass(), 42);
}
};
#include <memory>
class A {
public:
static shared_ptr<A> Create();
private:
A() {}
struct MakeSharedEnabler;
};
struct A::MakeSharedEnabler : public A {
MakeSharedEnabler() : A() {
}
};
shared_ptr<A> A::Create() {
return make_shared<MakeSharedEnabler>();
}
#include <memory>
class A
{
public:
static std::shared_ptr<A> create()
{
struct make_shared_enabler : public A {};
return std::make_shared<make_shared_enabler>();
}
private:
A() {}
};
struct A {
public:
template<typename ...Arg> std::shared_ptr<A> static create(Arg&&...arg) {
struct EnableMakeShared : public A {
EnableMakeShared(Arg&&...arg) :A(std::forward<Arg>(arg)...) {}
};
return std::make_shared<EnableMakeShared>(std::forward<Arg>(arg)...);
}
void dump() const {
std::cout << a_ << std::endl;
}
private:
A(int a) : a_(a) {}
A(int i, int j) : a_(i + j) {}
A(std::string const& a) : a_(a.size()) {}
int a_;
};
#include <memory>
#if defined(__cplusplus) && __cplusplus >= 201103L
#define ALLOW_MAKE_SHARED(x) friend void __gnu_cxx::new_allocator<test>::construct<test>(test*);
#elif defined(_WIN32) || defined(WIN32)
#if defined(_MSC_VER) && _MSC_VER >= 1800
#define ALLOW_MAKE_SHARED(x) friend class std::_Ref_count_obj;
#else
#error msc version does not suport c++11
#endif
#else
#error implement for platform
#endif
class test {
test() {}
ALLOW_MAKE_SHARED(test);
public:
static std::shared_ptr<test> create() { return std::make_shared<test>(); }
};
int main() {
std::shared_ptr<test> t(test::create());
}
#include <iostream>
#include <memory>
class A : public std::enable_shared_from_this<A>
{
private:
A(){}
explicit A(int a):m_a(a){}
public:
template <typename... Args>
static std::shared_ptr<A> create(Args &&... args)
{
class make_shared_enabler : public A
{
public:
make_shared_enabler(Args &&... args):A(std::forward<Args>(args)...){}
};
return std::make_shared<make_shared_enabler>(std::forward<Args>(args)...);
}
int val() const
{
return m_a;
}
private:
int m_a=0;
};
int main(int, char **)
{
std::shared_ptr<A> a0=A::create();
std::shared_ptr<A> a1=A::create(10);
std::cout << a0->val() << " " << a1->val() << std::endl;
return 0;
}
#include <memory>
#include <utility>
template<typename S>
struct enable_make : public S
{
template<typename... T>
enable_make(T&&... t)
: S(std::forward<T>(t)...)
{
}
};
class foo
{
public:
static std::unique_ptr<foo> create(std::unique_ptr<int> u, char const* s)
{
return std::make_unique<enable_make<foo>>(std::move(u), s);
}
protected:
foo(std::unique_ptr<int> u, char const* s)
{
}
};
void test()
{
auto fp = foo::create(std::make_unique<int>(3), "asdf");
}
namespace std {
class shared_ptr_access
{
template <typename _T, typename ... _Args>
static _T* __construct(void* __pv, _Args&& ... __args)
{ return ::new(__pv) _T(forward<_Args>(__args)...); }
template <typename _T>
static void __destroy(_T* __ptr) { __ptr->~_T(); }
template <typename _T, typename _A>
friend class __shared_ptr_storage;
};
}
class A {
public:
static std::shared_ptr<A> create() {
return std::make_shared<A>();
}
protected:
friend class std::shared_ptr_access;
A() {}
A(const A &) = delete;
const A &operator =(const A &) = delete;
};
class A;
typedef std::shared_ptr<A> APtr;
class A
{
template<class T>
friend class std::_Ref_count_obj;
public:
APtr create()
{
return std::make_shared<A>();
}
private:
A()
{}
};
#define SHARED_PTR_DECL(T) \
class T; \
typedef std::shared_ptr<T> ##T##Ptr;
#define FRIEND_STD_MAKE_SHARED \
template<class T> \
friend class std::_Ref_count_obj;
SHARED_PTR_DECL(B);
class B
{
FRIEND_STD_MAKE_SHARED
public:
BPtr create()
{
return std::make_shared<B>();
}
private:
B()
{}
};
typedef std::shared_ptr<A> APtr;
#include <iostream>
#include <memory>
class Factory final {
public:
template<typename T, typename... A>
static std::shared_ptr<T> make_shared(A&&... args) {
return std::allocate_shared<T>(Alloc<T>(), std::forward<A>(args)...);
}
private:
template<typename T>
struct Alloc : std::allocator<T> {
template<typename U, typename... A>
void construct(U* ptr, A&&... args) {
new(ptr) U(std::forward<A>(args)...);
}
template<typename U>
void destroy(U* ptr) {
ptr->~U();
}
};
};
class X final : public std::enable_shared_from_this<X> {
friend class Factory;
private:
X() { std::cout << "X() addr=" << this << "\n"; }
X(int i) { std::cout << "X(int) addr=" << this << " i=" << i << "\n"; }
~X() { std::cout << "~X()\n"; }
};
int main() {
auto p1 = Factory::make_shared<X>(42);
auto p2 = p1->shared_from_this();
std::cout << "p1=" << p1 << "\n"
<< "p2=" << p2 << "\n"
<< "count=" << p1.use_count() << "\n";
}
#include <iostream>
#include <memory>
class Factory final {
public:
template<typename T, typename... A>
static std::shared_ptr<T> make_shared(A&&... args) {
auto ptr = std::make_shared<Type<T>>(std::forward<A>(args)...);
return std::shared_ptr<T>(ptr, &ptr->type);
}
private:
template<typename T>
struct Type final {
template<typename... A>
Type(A&&... args) : type(std::forward<A>(args)...) { std::cout << "Type(...) addr=" << this << "\n"; }
~Type() { std::cout << "~Type()\n"; }
T type;
};
};
class X final {
friend struct Factory::Type<X>; // factory access
private:
X() { std::cout << "X() addr=" << this << "\n"; }
X(int i) { std::cout << "X(...) addr=" << this << " i=" << i << "\n"; }
~X() { std::cout << "~X()\n"; }
};
int main() {
auto ptr1 = Factory::make_shared<X>();
auto ptr2 = Factory::make_shared<X>(42);
}
#include <iostream>
#include <memory>
template<typename T>
class EnableShared {
friend class Factory; // factory access
public:
std::shared_ptr<T> shared_from_this() { return weak.lock(); }
protected:
EnableShared() = default;
virtual ~EnableShared() = default;
EnableShared<T>& operator=(const EnableShared<T>&) { return *this; } // no slicing
private:
std::weak_ptr<T> weak;
};
class Factory final {
public:
template<typename T, typename... A>
static std::shared_ptr<T> make_shared(A&&... args) {
auto ptr = std::make_shared<Type<T>>(std::forward<A>(args)...);
auto alt = std::shared_ptr<T>(ptr, &ptr->type);
assign(std::is_base_of<EnableShared<T>, T>(), alt);
return alt;
}
private:
template<typename T>
struct Type final {
template<typename... A>
Type(A&&... args) : type(std::forward<A>(args)...) { std::cout << "Type(...) addr=" << this << "\n"; }
~Type() { std::cout << "~Type()\n"; }
T type;
};
template<typename T>
static void assign(std::true_type, const std::shared_ptr<T>& ptr) {
ptr->weak = ptr;
}
template<typename T>
static void assign(std::false_type, const std::shared_ptr<T>&) {}
};
class X final : public EnableShared<X> {
friend struct Factory::Type<X>; // factory access
private:
X() { std::cout << "X() addr=" << this << "\n"; }
X(int i) { std::cout << "X(...) addr=" << this << " i=" << i << "\n"; }
~X() { std::cout << "~X()\n"; }
};
int main() {
auto ptr1 = Factory::make_shared<X>();
auto ptr2 = ptr1->shared_from_this();
std::cout << "ptr1=" << ptr1.get() << "\nptr2=" << ptr2.get() << "\n";
}