Specifically, the requirements on
make_shared
and
allocate_shared
are here;
http://eel.is/c++draft/util.smartptr.shared.create#1
the first paragraph's requirement is not met, because
AnimalFactory()
is private.
As @cubbi says, private member functions are only accessible from inside the class, not from standard library code.
You can write a thunk for make_shared() by leveraging a derived class, which probably shouldn't be part of the interface... if you're willing to make the constructor protected:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
# include <memory>
class A { protected: A() = default; A(int, int) {}; };
namespace {
struct A_derived final: A {
template<typename...Args>
A_derived(Args&&... args): A(std::forward<Args>(args)...) {}
};
}
template<typename... Args>
std::shared_ptr<A> make_shared_A(Args&&... args)
{ return std::make_shared<A_derived>(std::forward<Args>(args)...); }
int main() {
auto some_a1 = make_shared_A();
auto some_a2 = make_shared_A(1, 2);
}
|
http://coliru.stacked-crooked.com/a/74bf2d9f2dc248a9
Maybe someone can come up with a way to do this more nicely.
Note: (usually) the primary benefit of make_shared is exception-safety, not efficiency. Since it's a function, it forces the constructor arguments to be evaluated before the memory is allocated, which is not required in the case of plain new-expressions. Consider:
std::shared_ptr<T>(new T(might_throw());
Also, handing out
shared_ptr
is questionable.
Multiple invocations would yield independent shared_ptrs, leading to undefined behavior upon destruction. While you've made it impossible to do by caching the result of the first call, that seems opaque and could do with a comment.
Further, unique_ptr should be preferred unless you really have a need for shared ownership -- there is a danger of caching shared pointers cross-module and causing leaks that way.