[Edit: Turns out we don't even need reinterpret cast, making this even simpler]
This came up here and I found a better solution using reinterpret cast and shared pointer aliasing constructor. It allows both the ctor and dtor to be private, as well as use of the final specifier.
The reputation system won't let me leave this as an answer in that question, so I had to provide it as another question...
#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);
}
Giving the following output under gcc...
X() addr=0x62bc30
Type(...) addr=0x62bc30
X(...) addr=0x62bc50 i=42
Type(...) addr=0x62bc50
~Type()
~X()
~Type()
~X()
Just a followup... The approach above doesn't play well with std::enable_shared_from_this<> because the initial std::shared_ptr<> is to the wrapper and not the type itself. We can address this with an equivalent class that is compatible with the factory...
#include <iostream>
#include <memory>
template<typename T>
class EnableShared {
friend class Factory; // member 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";
}
Related
I have a polymorphic NVI class to provide an adapter for Runtime-Polymorphism.
Type-erasure is used for loose coupling.
The non-owning implementation can be optimized out in a compile-time context:
// usage just for reference
printer referenced{"Referenced"};
const auto &polymorphicPrinter = polymorphic(referenced);
polymorphicPrinter.print(8.15);
// how to optimize this?
const auto &owningPolymorhic = polymorphic(std::make_unique<printer>("Owned");
However, I am not sure what is a simple or elegant way to allow passing the ownership and still have optimization like in the above case when it is possible.
Here is my naive implementation. I also added std::bad_function_call for invalid state.
// api_header.h
#pragma once
#include <memory>
#include <string_view>
#include <functional>
class polymorphic final
{
public:
template <typename T>
polymorphic(const T& t)
: pVTable_(getVTable(t)),
pObj_(std::addressof(t), [](const void*){})
{}
template <typename T>
polymorphic(std::unique_ptr<const T> t)
: pVTable_(getVTable(*t)),
pObj_(t.release(), [](const void* pObj){
delete static_cast<const T*>(pObj);
})
{}
template <typename T>
polymorphic(std::unique_ptr<T> t)
: polymorphic(std::unique_ptr<const T>(t.release()))
{}
polymorphic(const polymorphic&) = delete;
polymorphic& operator=(const polymorphic&) = delete;
polymorphic(polymorphic&& other) noexcept
: pVTable_(other.pVTable_),
pObj_(std::move(other.pObj_))
{
other.pVTable_ = polymorphic::getInvalidVTable();
}
polymorphic& operator=(polymorphic &&other) noexcept
{
pVTable_ = other.pVTable_;
pObj_ = std::move(other.pObj_);
other.pVTable_ = polymorphic::getInvalidVTable();
return *this;
}
template <typename T>
void print(T v) const
{
pVTable_->print(pObj_.get(), v);
}
private:
polymorphic() = default;
struct v_table {
virtual void print(const void *, double) const
{
throw std::bad_function_call();
}
virtual void print(const void *, std::string_view) const
{
throw std::bad_function_call();
}
protected:
~v_table() = default;
};
static const v_table *getInvalidVTable()
{
struct : v_table {} constexpr static invalidVTable{};
return &invalidVTable;
}
template <typename T>
static const v_table *getVTable(const T&)
{
struct : v_table {
void print(const void *pObj, double v) const override
{
static_cast<const T*>(pObj)->print(v);
}
void print(const void *pObj, std::string_view v) const override
{
static_cast<const T*>(pObj)->print(v);
}
} constexpr static vTable{};
return &vTable;
}
private:
const v_table *pVTable_ = getInvalidVTable();
// TODO: optimisation-friendly?
std::unique_ptr<const void, std::function<void(const void*)>> pObj_;
};
// main.cpp
#include "api_header.h"
#include <cstddef>
#include <string>
#include <iostream>
class printer
{
public:
template <size_t L>
explicit printer(const char (&name)[L])
: name_(name, L)
{}
void print(int v) const
{
std::cout << name_ << ": " << v << std::endl;
}
void print(double v) const
{
std::cout << name_ << ": " << v << std::endl;
}
void print(std::string_view v) const
{
std::cout << name_ << ": " << v << std::endl;
}
~printer()
{
std::cout << name_ << " destroyed\n";
}
private:
std::string name_;
};
int main()
{
printer pReferenced{"referenced"};
{
const auto &polyReferenced = polymorphic(pReferenced);
polyReferenced.print(4);
polyReferenced.print(8.15);
polyReferenced.print("oceanic");
std::cout << "non-owning polymorphic destroyed\n\n";
}
{
const auto &polyOwned = polymorphic(std::make_unique<printer>("owned"));
polyOwned.print(4);
polyOwned.print(8.15);
polyOwned.print("oceanic");
}
std::cout << "owning polymorphic destroyed\n\n";
std::cout << "Invalidating polymorphic reference\n";
try {
auto invalidReferenced = polymorphic(pReferenced);
auto polyMoved = std::move(invalidReferenced);
polyMoved.print("I have been moved");
invalidReferenced.print("This will throw");
}
catch (const std::bad_function_call &e)
{
std::cout << "error: " << e.what() << std::endl;
}
}
This code:
https://godbolt.org/z/Pc8981ns8
Is it possible to make this code optimization-friendly?
Is there an way to call different constructors of same class based on different template parameter.
template<class T>
class X {
public:
T a;
X<char>() {
std::cout << "char ctor called" << std::endl;
}
X<int>() {
std::cout << "int ctor called" << std::endl;
}
};
int main() {
X<char> x;
X<int> y;
}
I think constructors in the class are not valid, but is there any other way to do that?
There are several ways:
(full) specialization of the member:
template<class T>
class X {
public:
T a;
X();
};
template <>
X<char>::X() : a('\0') { std::cout << "char ctor called" << std::endl; }
template <>
X<int>::X() : a(0) { std::cout << "int ctor called" << std::endl; }
Specialize the whole class (so requires to duplicate some code though)
template<class T>
class X;
template <>
class X<char> {
public:
char a;
X() : a('\0') { std::cout << "char ctor called" << std::endl; }
};
template <>
class X<int> {
public:
int a;
X() : a(0) { std::cout << "int ctor called" << std::endl; }
};
if constexpr of C++17 (but doesn't handle initializer list):
template<class T>
class X {
public:
T a;
X() : a(0) {
if constexpr (std::is_same_v<char, T>) {
std::cout << "char ctor called" << std::endl;
} else if constexpr (std::is_same_v<int, T>) {
std::cout << "int ctor called" << std::endl;
}
}
};
requires for C++20:
template<class T>
class X {
public:
T a;
X() requires(std::is_same_v<char, T>) : a('\0') {
std::cout << "char ctor called" << std::endl;
}
X() requires(std::is_same_v<int, T>) : a(0) {
std::cout << "int ctor called" << std::endl;
}
};
You can use if constexpr:
template <class T>
class X {
public:
// ...
X()
{
if constexpr (std::is_same_v<T, int>) {
// ...
} else if constexpr (std::is_same_v<T, char>) {
// ...
} else {
// ...
}
}
};
Just another alternative - tag dispatch:
template<class T>
class X {
public:
// ...
X() : X(Tag<T>{}) {}
private:
template<class> struct Tag {};
X(Tag<char>) {
// ...
}
X(Tag<int>) {
// ...
}
template<class U> X(Tag<U>) {
// ...
}
};
Yes,see http://www.cplusplus.com/doc/oldtutorial/templates/
You can do this:
template<class T>
class X {
public:
T a;
X() {
std::cout << "basic template\n" ;
}
};
template<>
class X<char> {
public:
char a;
X() {
std::cout << "char ctor called\n" ;
}
};
template<>
class X<int> {
public:
int a;
X() {
std::cout << "int ctor called\n";
}
};
int main(){
X<int> xint;
X<char> xchar;
X<string> xstring;
return 0;
}
You will see in the output window:
int ctor called
char ctor called
basic template
I'm trying to write a factory class which will have a standard interface that looks like this:
Register<MyBase, MyDerived> g_regDerived("myderived"); // register to factory
now calling:
auto* d = Factory<MyBase>::instance().create("myderived", 1, 2, 3);
will invoke the constructor MyDerived(1,2,3) and return a pointer to the created object
This sounds like something that should be possible with C++11 but I could not figure out how to do it.
Starting from a standard type-erasure factory:
template<typename BaseT>
class Factory {
public:
static Factory* instance() {
static Factory inst;
return &inst;
}
template<typename T>
void reg(const string& name) {
m_stock[name].reset(new Creator<T>);
}
BaseT* create(const string& name) {
return m_stock[name]->create();
}
private:
struct ICreator {
virtual BaseT* create() = 0;
};
template<typename T>
struct Creator : public ICreator {
virtual BaseT* create() {
return new T;
}
};
std::map<string, std::unique_ptr<ICreator>> m_stock;
};
template<typename BaseT, typename T>
class Register {
public:
Register(const QString& name) {
Factory<BaseT>::instance()->reg<T>(name);
}
};
The problem here is fact that once you erase the type of the created object, you can no longer pass arbitrary template forwarded arguments since you need to pass them through a virtual function.
The answer to this question:
How to pass a function pointer that points to constructor?
talks about something similar but the answer there is to go through a function which is specific for every derived class. I want to use the class constructor directly and not have to write a create() function.
I don't know why your aversion to writing a create() function. So here is one that I implemented.
#include <iostream>
#include <utility>
using namespace std;
class C
{
public:
virtual char const* whoAmI() const = 0;
};
class A : public C
{
public:
A(int a1)
{
cout << "A(" << a1 << ")" << endl;
}
A(float a1)
{
cout << "A(" << a1 << ")" << endl;
}
virtual char const* whoAmI() const override
{
return "A";
}
};
class B : public C
{
public:
B(int a1)
{
cout << "B(" << a1 << ")" << endl;
}
B(float a1)
{
cout << "B(" << a1 << ")" << endl;
}
virtual char const* whoAmI() const override
{
return "B";
}
};
template<typename BASET>
class Factory
{
public:
// could use a is_base type trait test here
template <typename T, typename...ARGs>
static BASET* create(ARGs&&...args)
{
return new T(forward<ARGs>(args)...);
}
};
int main()
{
Factory<C> factory;
C* a = factory.create<A>(1);
C* b = factory.create<B>(1.0f);
cout << a->whoAmI() << endl;
cout << b->whoAmI() << endl;
return 0;
}
NOTE: I didn't do everything that yours does, I merely implemented the create function. I leave the final implementation up to you.
This uses perfect forwarding to enable a varidict template to pass any number of parameters to a constructor. Your register function can then store a function pointer of a particular template instance, for a particular parameter set.
EDIT
I forgot to use the appropriate forward<ARGs>(args)... call to implement perfect forwarding. It has now been added.
As for you thinking that this is not useful, here is the full implementation of your factory using perfect forwarding and varidict templates allowing a specific number of parameters of particular types for a particular factory instance:
#include <string>
#include <map>
#include <memory>
#include <utility>
#include <iostream>
using namespace std;
template<typename BaseT, typename...ARGs>
class Factory {
public:
static Factory* instance() {
static Factory inst;
return &inst;
}
template<typename T>
void reg(const string& name) {
m_stock[name].reset(new Creator<T>);
}
BaseT* create(const string& name, ARGs&&...args) {
return m_stock[name]->create(forward<ARGs>(args)...);
}
private:
struct ICreator
{
virtual BaseT* create(ARGs&&...) = 0;
};
template<typename T>
struct Creator : public ICreator {
virtual BaseT* create(ARGs&&...args) override
{
return new T(forward<ARGs>(args)...);
}
};
std::map<string, std::unique_ptr<ICreator>> m_stock;
};
template<typename BaseT, typename T, typename...ARGs>
class Register {
public:
Register(const string& name) {
auto instance = Factory<BaseT, ARGs...>::instance();
instance->template reg<T>(name);
}
};
struct C
{
virtual char const * whoAmI() const = 0;
};
struct A : public C
{
A(int a1, int a2)
{
cout << "Creating A(" << a1 << ", " << a2 << ")" << endl;
}
virtual char const * whoAmI() const override
{
return "A";
}
};
struct B : public C
{
B(int b1, int b2)
{
cout << "Creating B(" << b1 << ", " << b2 << ")" << endl;
}
B(int b1, int b2, int b3)
{
cout << "Creating B(" << b1 << ", " << b2 << ", " << b3 << ")" << endl;
}
virtual char const * whoAmI() const override
{
return "B";
}
};
typedef int I;
Register<C, A, I, I> a("a");
Register<C, B, I, I> b("b");
Register<C, B, I, I, I> b3("b");
int main()
{
C* a = Factory<C, I, I>::instance()->create("a", 1, 2);
C* b = Factory<C, I, I>::instance()->create("b", 3, 4);
C* b3 = Factory<C, I, I, I>::instance()->create("b", 5, 6, 7);
cout << "I am a " << a->whoAmI() << endl;
cout << "I am a " << b->whoAmI() << endl;
cout << "I am a " << b3->whoAmI() << endl;
return 0;
}
Is that what you want? If you don't want to deal with the function parameters, use a helper template function to deduce them for you like so:
template <typename BaseT, typename...ARGs>
BaseT* create(const string& name, ARGs&&...args)
{
return Factory<C, ARGs...>::instance()->create(name, forward<ARGs>(args)...);
}
int main()
{
C* a = create<C>("a", 1, 2);
C* b = create<C>("b", 3, 4);
C* b3 = create<C>("b", 3, 4, 5);
cout << "I am a " << a->whoAmI() << endl;
cout << "I am a " << b->whoAmI() << endl;
cout << "I am a " << b3->whoAmI() << endl;
return 0;
}
Which has the added bonus of allowing multiple constructor signatures available through the apparent single function API (it only looks like one, but is actually N where N is the number of different signatures you allow). This all can be viewed through this online demo.
You'll still need to use the same registration as I depicted before though, which could be shortened by way of a macro.
If this is still not what you want, then add additional detail to your question.
Next code:
#include <typeinfo>
#include <iostream>
struct A
{
A() : _m('a'){ std::cout << "A()" << std::endl; }
void f(){ std::cout << "A::f() " << _m << std::endl; }
char _m;
};
struct B
{
B() : _m('b'){ std::cout << "B()" << std::endl; }
void f(){ std::cout << "B::f() " << _m << std::endl; }
char _m;
};
struct C
{
C() : _m('c'){ std::cout << "C()" << std::endl; }
void f(){ std::cout << "C::f() " << _m << std::endl; }
char _m;
};
template<typename T>
void f(T t = T());
template<typename T>
void f(T t)
{
std::cout << typeid(t).name() << std::endl;
t.f();
}
int main()
{
f<A>();
f<B>();
f<C>();
}
Has this output when using VS2008, VS2010 and VS2012:
A()
struct A
A::f() a
A()
struct B
B::f() a
A()
struct C
C::f() a
Is this a known compiler bug?
Please note that it works as expected in VS2013.
Your compiler might be confused because you have a function template declaration, followed by something that looks like a function template partial specialization. GCC correctly rejects your code.
To be precise, this is the problem:
template<typename T>
void f<T>(T t) { .... }
// ^^^
If you really want to separate declaration and definition, you would need
template<typename T>
void f(T t) { .... }
This would be a well-formed version of your program:
#include <iostream>
#include <typeinfo>
struct A {}; // as before
struct B {}; // as before
struct C {}; // as before
template<typename T>
void f(T t = T())
{
std::cout << typeid( t ).name() << std::endl;
t.f();
}
int main()
{
f<A>();
f<B>();
f<C>();
}
Why executing this code:
// DefaultAny.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <exception>
using std::cout;
template<class T>
struct NoReturnPolicy
{
static void calculate(T& result, const T& source)
{
result = source;
}
};
template<class T>
struct ReturnPolicy
{
static T& calculate(T& result, const T& source)
{
result = source;
return result;
}
};
template<class T>
struct ThrowPolicy
{
static void check(T* ptr)
{
cout << "ThrowPolicy";
struct Nullptr: public std::exception{};
if(!ptr)
{
throw Nullptr("Nullptr not allowed");
}
}
};
template<class T>
struct NoThrowPolicy
{
static T* check(T* ptr)
{
cout << "NoThrowPolicy";
if(!ptr)
{
return nullptr;
}
else
{
return ptr;
}
}
};
/*
If pointer already points at
something no assignement is being done
*/
template<class T, class ThrowingPolicy>
struct NoAssignPolicy
{
static T* check(T* dest,const T*const src)
{
cout << "NoAssignPolicy";
if (!ThrowPolicy::check(dest))
{
dest = operator new(sizeof(T));
new (dest) T(*src);
}
}
};
template<class T,class ThrowingPolicy>
struct NoCheckPolicy
{
static void check(T* p)
{
cout << "NoCheckPolicy";
}
};
template<class T,class ThrowingPolicy>
struct CheckPolicy
{
static void check(T* p)
{
cout << "CheckPolicy";
ThrowingPolicy::check(p);
}
};
template<
class T,
class ThrowingPolicy = NoThrowPolicy<T>,
class CheckingPolicy = NoCheckPolicy<T,ThrowingPolicy>,
class AssigningPolicy = NoAssignPolicy<T,ThrowingPolicy>,
class ReturningPolicy = NoReturnPolicy<T>
>
struct BreadSlicer
{
BreadSlicer()
{
cout << "Type: " << typeid(T).name() << '\n';
cout << "ThrowingPolicy: " << ThrowingPolicy::check(0) << '\n'; //
//<<<---------The second call to cout makes output on my console:
//NoThrowPolicy:"NoSpace"ThrowingPolicy:"Space"000000
}
};
//The words NoSpace and Space do not actually appear in my console ;) and they are in the opposite order.
int _tmain(int argc, _TCHAR* argv[])
{
BreadSlicer<int> a;
return 0;
}
See comments in first struct above main.
This is the result of unspecified behavior. If you have:
cout << a() << b() << c() << endl;
The order of execution of a, b, and c is not defined (yes, their results are added to the cout stream in a predictable order, but execution of the functions is not in defined order).
If your question is why "NoThrowPolicy" gets output before "ThrowingPolicy", the answer is that there's no sequence point guaranteeing an ordering for the call to ThrowingPolicy::check(0) and the call to operator<<(cout, "ThrowingPolicy: "). C++ is allowed to call those functions in either order.