I'm not exactly sure how to word this in English, but I want to do something like this:
template <class T>
class derived: public T
{ blah };
Where basically, I have a template class, but I'm deriving a new class from the class that is specified in the template? I.e. so I wouldn't necessarily know the class at compile time.
Is this even possible? If so, What are the semantics for this?
For example, say I'm trying to write a "parent" class. For the purposes of this example, let's say it's a tree parent. The tree parent, is a tree itself (so it inherits from tree), but also has a vector of references to child trees.However, the parent class itself doesn't have to be a tree; it could be any class, such that I could write something like:
Parent<tree> treeParent;
Parent<shrub> shrubParent;
Yes. That is possible. Try doing that.
I wouldn't necessarily know the class at compile time.
I think, you mean "I wouldn't necessarily know the class at the time of defining the class template."
By the time you compile, you've already defined the class template, and used it in your code, passing template argument to it, which means you know the class (i.e template argument) at compile time. If you don't know the class to be used as base, then you cannot even compile the code.
This is indeed possible and commonly used for policy based design:
Like in this incredibly contrived example:
template<typename OutputPolicy>
struct Writer : public OutputPolicy {
using OutputPolicy::print;
void write(const std::string&) {
//do some formatting etc.
print(string);
}
};
class StdoutPolicy {
public:
set_linebreaks(const std::string&);
protected:
void print(const std::string&);
};
The public method in the policy will be accessible through Writer. That way a policy can decorate the class it is used in with additional methods.
Yes this is possible. The semantic for this is no different from the semantic for any other use of a template parameter in the class template. You can have a member of type T, a function parameter of type T, and you can have T as a base class too. It's not special.
Like this:
#include <iostream>
using namespace std;
template<typename T>class classTemplateBase
{
public:
T value;
classTemplateBase(T i)
{
this->value = i;
}
void test()
{
cout << value << endl;
}
};
class classTemplateChild : public classTemplateBase<char>
{
public:
classTemplateChild( ): classTemplateBase<char>( 0 ) // default char is NUL
{
;
}
classTemplateChild(char c): classTemplateBase<char>( c )
{
;
}
void test2()
{
test();
}
};
int main()
{
classTemplateBase <int> a( 42 );
classTemplateChild b( 'A' );
a.test(); // should print "42"
b.test(); // should print "A"
b.test2(); // should print "A"
return 0;
}
This is possible an it is also very common and has gotten it's own name: the Curiously recurring template pattern. See the Wikipeida entry on Curiously recurring template pattern.
Related
I'm not sure what I am asking for is possible.
I have a templated class called Controller. This is a variadic template class which takes multiple classes and can set their values as such.
Controller<ClassA,ClassB,ClassC>* myController = new Controller<ClassA,ClassB,ClassC>(*a,*b,*c);
myController->setValues(32);
This takes a bunch of different classes together and allows me to to set their values at the same time. setValues is a templated function which allows any type to be passed in. However, right now I am trying to modify my class so that I can set a value within the controller itself for easy retrieval. However this is the part that is proving difficult.
template<typename...Classes>
class Controller
{
public:
Controller(Classes&...objects) : objects(objects...){}
Controller(std::tuple<Classes&...> tup) : objects(tup){}
template<typename T>
void setValues(T value)
{
std::apply([&](auto&...x) { x.updateValue(value),...);}, objects); //calls the updateValue function for each class
}
private:
std::tuple<Classes&...> objects;
};
I want to add the following as a private variable T controllerValue; However, I know that I cannot simply declare T because we cannot define member templates and the compiler has no idea what to expect. Which then I tried to create a private struct:
template<typename T>
struct ControllerValue { T value; };
However, I cannot define a struct underneath that, because the same problem occurs. The compiler has no idea what type ControllerValue is. What I would like is something like this:
template<typename...Classes>
class Controller
{
public:
Controller(Classes&...objects) : objects(objects...){}
Controller(std::tuple<Classes&...> tup) : objects(tup){}
template<typename T>
void setValues(T value)
{
thisValue.value = value;
std::apply([&](auto&...x) { x.updateValue(value),...);}, objects); //calls the updateValue function for each class
}
template<typename T>
T getValue() const { return thisValue.value }
private:
std::tuple<Classes&...> objects;
template<typename T>
struct ControllerValue { T value; };
ControllerValue thisValue;
};
This will not compile at all for the same reason that the compiler has no idea what type ControllerValue should be. And this is where I am stuck. Is this even possible to do? If not, what is another way that I can make this work?
To clear up confusion, the use case would be something like this:
Controller<ClassA,ClassB,ClassC>* myController = new Controller<ClassA,ClassB,ClassC>(*a,*b,*c);
myController->setValues(32);
int commonValue = myController->getValue();
or
Controller<ClassA,ClassB,ClassC>* myController = new Controller<ClassA,ClassB,ClassC>(*a,*b,*c);
myController->setValues(32.3);
double commonValue = myController->getValue();
I think solving this exact problem is impossible in C++ (and still very cumbersome in languages with runtime generics). You can very easily create a polymorphic class that can only store any value:
class PolymorphicBase
{
public:
virtual ~PolymorphicBase() = default;
};
template <class T>
class PolymorphicObject : public PolymorphicBase
{
T value;
public:
PolymorphicObject(T value) : value(std::move(value))
{
}
};
A member of std::unique_ptr<PolymorphicBase> can sufficiently store any value, but how would such a value be retrieved? Probably the easiest is to expose the reference to PolymorphicBase and use dynamic type checks to see if the type is compatible with something you know, but what if you need the code to work for any type?
This is what lambdas with auto parameters are useful for. However, you would have to be able to pass such a lambda to a method on PolymorphicBase and implement that method in PolymorphicObject. This is impossible, since you cannot override a method template (it needs to be a template to accept a lambda) – that's where the compile-time and runtime parts of C++ clash. And there is simply no type in C++ that represents a function accepting any parameter (and knowing its type), which is a template by itself.
You can partially solve this by making the type of the lambda known to PolymorphicBase:
template <class Retriever>
class PolymorphicBase
{
public:
virtual void retrieve(Retriever func) = 0;
virtual ~PolymorphicBase() = default;
};
template <class Retriever, class T>
class PolymorphicObject : public PolymorphicBase<Retriever>
{
T value;
public:
PolymorphicObject(T value) : value(std::move(value))
{
}
void retrieve(Retriever func) override
{
func(value);
}
};
auto lambda = [](auto arg)
{
std::cout << arg << std::endl;
};
PolymorphicObject<decltype(lambda), int> obj(6);
PolymorphicBase<decltype(lambda)> &ptr = obj;
ptr.retrieve(lambda);
This is useful if you ever have only a single way to retrieve the value.
I don't think this is needed in most cases anyway. Usually you use a fixed set of types as the values, so you can use a variant there, or they all implement a common interface, or (as you've pointed out in the comments) you actually meant to move the type parameter from the method to the class (which allows you to check that all the types actually support the value earlier than originally).
However, I agree that in languages with generics/templates it is somewhat hard to have a method that can actually choose its result type in a generic fashion, without being controlled by outside parameters.
I'm trying to implement user defaults in my C++ app.
For that I created an interface class with one function in it:
class IRegisterUserDefaults
{
public:
IRegisterUserDefaults();
virtual void registerUserDefaults(){}
};
Each class inheriting from this interface class will implement the function to register the user defaults it needs to be set.
So far no problem. But what's the best way of calling it?
I'm coming from Objective-C where I could just search through all classes and find the ones who implement the interface and call the registerUserDefaults function on them. I understand though that C++ doesn't have this level of introspection. It would be sufficient to call the function once per class (and thus make it static).
Objective
It would be great if the function would be called "automatically" if a class subclasses IRegisterUserDefaults. I tried calling the method from the IRegisterUserDefaults constructor but it looks like this doesn't call the subclass function properly. Is there a way to make this happen?
Also, what would be best way to make sure this is only called once per class?
IRegisterUserDefaults is not a meaningful interface, in any language.
It sounds like the actual problem you are trying to solve is "run some code once, at or near class first use". You can do that with something like this
class HasUserDefaults {
static std::once_flag register_once;
void registerUserDefaults() { /*...*/ }
public:
HasUserDefaults ()
{
// in all the constructors
std::call_once(register_once, &HasUserDefaults::registerUserDefaults, this);
}
// other members
};
Do you have a single location where all those derived classes are known? In that case, do it there:
// The type-list can be used in many ways, as you need
using all_classes = std::tuple<A, B, C, D /* and so on */>;
template <class... Ts>
static void register_all_classes(Y<Ts...>*)
{ ((Ts().registerUserDefaults()), ...); }
register_all_classes((all_classes*)nullptr);
Otherwise, you must obviously go decentralized:
Do you have a single compilation-unit responsible for registering each class? In that case, use a namespace-scope object. Maybe use a helper for that:
template <class T>
struct Init {
Init() { T().registerUserDefaults(); }
};
// Used in single TU as:
static Init<SomeRegisterUserDefaults> _;
Otherwise, take a look at std::ios_base::Init how <iostream> does it. I simplified because there was no need for uninit indicated:
template <class T>
struct MultiInit {
MultiInit() { static Init<T> _; }
};
// Used in any number of TUs as:
static MultiInit<SomeRegisterUserDefaults> _;
Does this work for you?
#include <iostream>
#include <string>
class IRegisterUserDefaults
{
public:
IRegisterUserDefaults() {}
virtual void registerUserDefaults() = 0;
};
class MoreDerivedRegisterUserDefaults : public IRegisterUserDefaults
{
public:
MoreDerivedRegisterUserDefaults (int x, int y) : m_x (x), m_y (y) { }
virtual void registerUserDefaults() override {
std::cout << "MoreDerivedRegisterUserDefaults::registerUserDefaults called (" << m_x << ", " << m_y << ")" << std::endl;
}
private:
int m_x, m_y;
};
template <class T, typename... Args> void RegisterDefaultsHandler (Args... args) {
T obj (args...);
obj.registerUserDefaults ();
}
int main ()
{
RegisterDefaultsHandler<DerivedRegisterUserDefaults> ();
RegisterDefaultsHandler<MoreDerivedRegisterUserDefaults> (1, 2);
// ...
}
You have to instantiate each derived class somewhere.
Live demo (updated). Output:
DerivedRegisterUserDefaults::registerUserDefaults called
MoreDerivedRegisterUserDefaults::registerUserDefaults called (1, 2)
EDIT: After talking to #Caleth, I tweaked the code a little to make my intentions clearer.
EDIT 2: Variadiac template added, turned out to be easier than I thought, useful 'howto' guide here.
Call the method in sub-class constructor, you cannot call this in base class constructor as the sub class is not yet constructed by then.
I have a function User::func()(callback) that would be called by a template class (Library<T>).
In the first iteration of development, everyone know that func() serves only for that single purpose.
A few months later, most members forget what func() is for.
After some heavy refactoring, the func() is sometimes deleted by some coders.
At first, I didn't think this is a problem at all.
However, after I re-encountered this pattern several times, I think I need some counter-measure.
Question
How to document it elegantly? (cute && concise && no additional CPU cost)
Example
Here is a simplified code:-
(The real world problem is scattering around 10+ library-files & 20+ user files & 40+ functions.)
Library.h
template<class T> class Library{
public: T* node=nullptr;
public: void utility(){
node->func(); //#1
}
};
User.h
class User{
public: void func(){/** some code*/} //#1
//... a lot of other functions ...
// some of them are also callback of other libraries
};
main.cpp
int main(){
Library<User> li; .... ; li.utility();
}
My poor solutions
1. Comment / doc
As the first workaround, I tend to add a comment like this:-
class User{
/** This function is for "Library" callback */
public: void func(){/** some code*/}
};
But it gets dirty pretty fast - I have to add it to every "func" in every class.
2. Rename the "func()"
In real case, I tend to prefix function name like this:-
class User{
public: void LIBRARY_func(){/** some code*/}
};
It is very noticeable, but the function name is now very longer.
(especially when Library-class has longer class name)
3. Virtual class with "func()=0"
I am considering to create an abstract class as interface for the callback.
class LibraryCallback{
public: virtual void func()=0;
};
class User : public LibraryCallback{
public: virtual void func(){/** some code*/}
};
It provides feeling that func() is for something-quite-external. :)
However, I have to sacrifice virtual-calling cost (v-table).
In performance-critical cases, I can't afford it.
4. Static function
(idea from Daniel Jour in comment, thank!)
Almost 1 month later, here is how I use :-
Library.h
template<class T> class Library{
public: T* node=nullptr;
public: void utility(){
T::func(node); //#1
}
};
User.h
class User{
public: static void func(Callback*){/** some code*/}
};
main.cpp
int main(){
Library<User> li;
}
It is probably cleaner, but still lack self-document.
func is not a feature of User. It is a feature of the User-Library<T> coupling.
Placing it in User if it doesn't have clear semantics outside of Library<T> use is a bad idea. If it does have clear semantics, it should say what it does, and deleting it should be an obviously bad idea.
Placing it in Library<T> cannot work, because its behavior is a function of the T in Library<T>.
The answer is to place it in neither spot.
template<class T> struct tag_t{ using type=T; constexpr tag_t(){} };
template<class T> constexpr tag_t<T> tag{};
Now in Library.h:
struct ForLibrary;
template<class T> class Library{
public: T* node=nullptr;
public: void utility(){
func( tag<ForLibrary>, node ); // #1
}
};
in User.h:
struct ForLibrary;
class User{
/** This function is for "Library" callback */
public:
friend void func( tag_t<ForLibrary>, User* self ) {
// code
}
};
or just put this into the same namespace as User, or the same namespace as ForLibrary:
friend func( tag_t<ForLibrary>, User* self );
Before deleting func, you'll track down ForLibrary.
It is no longer part of the "public interface" of User, so doesn't clutter it up. It is either a friend (a helper), or a free function in the same namespace of either User or Library.
You can implement it where you need a Library<User> instead of in User.h or Library.h, especially if it just uses public interfaces of User.
The techniques used here are "tag dispatching", "argument dependent lookup", "friend functions" and preferring free functions over methods.
From the user side, I would use crtp to create a callback interface, and force Users to use it. For example:
template <typename T>
struct ICallbacks
{
void foo()
{
static_cast<T*>(this)->foo();
}
};
Users should inherit from this interface and implement foo() callback
struct User : public ICallbacks<User>
{
void foo() {std::cout << "User call back" << std::endl;}
};
The nice thing about it is that if Library is using ICallback interface and User forget to implement foo() you will get a nice compiler error message.
Note that there is no virtual function, so no performance penalty here.
From the library side, I would only call those callbacks via its interfaces (in this case ICallback). Following OP in using pointers, I would do something like this:
template <typename T>
struct Library
{
ICallbacks<T> *node = 0;
void utility()
{
assert(node != nullptr);
node->foo();
}
};
Note that things get auto documented in this way. It is very explicit that you are using a callback interface, and node is the object who has those functions.
Bellow a complete working example:
#include <iostream>
#include <cassert>
template <typename T>
struct ICallbacks
{
void foo()
{
static_cast<T*>(this)->foo();
}
};
struct User : public ICallbacks<User>
{
void foo() {std::cout << "User call back" << std::endl;}
};
template <typename T>
struct Library
{
ICallbacks<T> *node = 0;
void utility()
{
assert(node != nullptr);
node->foo();
}
};
int main()
{
User user;
Library<User> l;
l.node = &user;
l.utility();
}
Test.h
#ifndef TEST_H
#define TEST_H
// User Class Prototype Declarations
class User;
// Templated Wrapper Class To Contain Callback Functions
// User Will Inherit From This Using Their Own Class As This
// Class's Template Parameter
template <class T>
class Wrapper {
public:
// Function Template For Callback Methods.
template<class U>
auto Callback(...) {};
};
// Templated Library Class Defaulted To User With The Utility Function
// That Provides The Invoking Of The Call Back Method
template<class T = User>
class Library {
public:
T* node = nullptr;
void utility() {
T::Callback(node);
}
};
// User Class Inherited From Wrapper Class Using Itself As Wrapper's Template Parameter.
// Call Back Method In User Is A Static Method And Takes A class Wrapper* Declaration As
// Its Parameter
class User : public Wrapper<User> {
public:
static void Callback( class Wrapper* ) { std::cout << "Callback was called.\n"; }
};
#endif // TEST_H
main.cpp
#include "Test.h"
int main() {
Library<User> l;
l.utility();
return 0;
}
Output
Callback was called.
I was able to compile, build and run this without error in VS2017 CE on Windows 7 - 64bit Intel Core 2 Quad Extreme.
Any Thoughts?
I would recommend to name the wrapper class appropriately, then for each specific call back function that has a unique purpose name them accordingly within the wrapper class.
Edit
After playing around with this "template magic" well there is no such thing...
I had commented out the function template in the Wrapper class and found that it is not needed. Then I commented out the class Wrapper* that is the argument list for the Callback() in User. This gave me a compiler error that stated that User::Callback() does not take 0 arguments. So I looked back at Wrapper since User inherits from it. Well at this point Wrapper is an empty class template.
This lead me to look at Library. Library has a pointer to User as a public member and a utility() function that invokes User's static Callback method. It is here that the invoking method is taking a pointer to a User object as its parameter. So it lead me to try this:
class User; // Prototype
class A{}; // Empty Class
template<class T = User>
class Library {
public:
T* node = nullptr;
void utility() {
T::Callback(node);
}
};
class User : public A {
public:
static void Callback( A* ) { std::cout << "Callback was called.\n"; }
};
And this compiles and builds correctly as the simplified version. However; when I thought about it; the template version is better because it is deduced at compile time and not run time. So when we go back to using templates javaLover had asked me what class Wrapper* means or is within the argument list for the Callback method within the User class.
I'll try to explain this as clearly as I can but first the wrapper Class is just an empty template shell that User will inherit from and it does nothing but act as a base class and it now looks like this:
template<class T>
class Wrapper { // Could Be Changed To A More Suitable Name Such As Shell or BaseShell
};
When we look at the User class:
class User : public Wrapper<User> {
public:
static void Callback( class Wrapper* ) { // print statement }
};
We see that User is a non-template class that inherits from a template class but uses itself as the template's argument. It contains a public static method
and this method doesn't return any thing but it does take a single parameter; this is also evident in the Library class that has its template parameter as a User class. When the Library's utility() method invokes User's Callback() method the parameter that the Library is expecting is a pointer to a User object. So when we go back to the User class instead of declaring it as a User* pointer directly in its declaration I'm using the empty class template that it inherits from. However if you try to do this:
class User : public Wrapper<User> {
public:
static void Callback( Wrapper* ) { // print statement }
};
You should get a message that Wrapper* is missing it's argument list. We could just do Wrapper<User>* here but that is redundant since we already see that User is inheriting from Wrapper that takes itself. So we can fix this and make it cleaner just by prefixing the Wrapper* with the class keyword since it is a class template. Hence the template magic... well there is no magic here... just compiler intrinsic and optimizations.
While I know that I don't answer your specific question (how to document the not-to-be-deleted function) I would solve your problem (keeping the seemingly unused callback function in the code base) by instantiating Library<User> and calling the utility() function in a unit test (or maybe it should rather be called an API test...). This solution would probably scale to your real world example too, as long as you don't have to check each possible combination of library classes and callback functions.
If you are lucky enough to work in an organization where successful unit tests and code review are required before changes go into the code base this would require a change to the unit tests before anyone could remove the User::func() function and such a change would probably catch the attention of a reviewer.
Then again, you know your environment and I don't, and I'm aware that this solution doesn't fit all situations.
Here is a solution using a Traits class:
// Library.h:
template<class T> struct LibraryTraits; // must be implemented for every User-class
template<class T> class Library {
public:
T* node=nullptr;
void utility() {
LibraryTraits<T>::func(node);
}
};
// User.h:
class User { };
// must only be implemented if User is to be used by Library (and can be implemented somewhere else)
template<> struct LibraryTraits<User> {
static void func(User* node) { std::cout << "LibraryTraits<User>::func(" << node << ")\n"; }
};
// main.cpp:
int main() {
Library<User> li; li.utility();
}
Advantages:
It is obvious by the naming that LibraryTraits<User> is only required for interfacing User by Library (and can be removed, once either Library or User gets removed.
LibraryTraits can be specialized independent of Library and User
Disadvantages:
No easy access to private members of User (making LibraryTraits a friend of User would remove the independence).
If the same func is needed for different Library classes multiple Trait classes need to be implemented (could be solved by default implementations inheriting from other Trait classes).
This heavily reminds an old good Policy-Based Design, except in your case you do not inherit the Library class from the User class.
Good names are the best friends of any API. Combine this and the well-known patter of Policy-Based Design (well-known is very important because the class names with the word Policy in it will immediately ring the bell in many readers of the code) and, I assume, you get a well self-documenting code.
Inheritance won't give you any performance overhead, but will give you an ability to have the Callback as a protected method, that will give some hint that it is supposed to be inherited and be used somewhere.
Have clearly standing-out and consistent naming among multiple User-like classes (e.g. SomePolicyOfSomething in the manner of aforementioned Policy-Based Design), as well as, the template arguments for the Library (e.g SomePolicy, or I would call it TSomePolicy).
Having using declaration of the Callback in the Library class might give much clearer and earlier errors (e.g. from IDE, or modern clang, visial studio syntax parsers for IDE).
Another arguable option might be a static_assert if you have C++>=11. But in this case it must be used in every User-like class ((.
Not a direct answer to your question on how to document it, but something to consider:
If your Library template requires an implementation of someFunction() for each class to be used in it, i'd recommend adding it as a template argument.
#include <functional>
template<class Type, std::function<void(Type*)> callback>
class Library {
// Some Stuff...
Type* node = nullptr;
public:
void utility() {
callback(this->node);
}
};
Might make it even more explicit, so that other devs know it's needed.
abstract class is the best way to enforce the function not to be deleted. So i recommend implementing the base class with pure virtual function, so that derived has to define the function.
OR second solution would be to have function pointers so that performance will be saved by avoiding extra overhead of V-table creation and calling.
If it is not obvious that func() is needed in User, then I'd argue you're violating the single responsibility principle. Instead create an adapter class of which User as a member.
class UserCallback {
public:
void func();
private:
User m_user;
}
That way the existance of UserCallback documents that func() is an external call back, and separates out Library's need of a callback from the actual responsibilities of User.
I want to implement a class hierarchy for object dispatching. Different classes dispatch different elements, and each class can dispatch its element represented as different data types.
It is better understood through a (faulty) example. This is what I would like to have if virtual function templating was allowed:
class Dispatcher {
template <class ReturnType>
virtual ReturnType getStuffAs();
};
So that I can implement subclasses as:
class CakeDispatcher : public Dispatcher {
template <>
virtual Recipe getStuffAs(){ ... }
template <>
virtual Baked getStuffAs(){ ... }
};
class DonutDispatcher : public Dispatcher {
template <>
virtual Frozen getStuffAs(){ ... }
template <>
virtual Baked getStuffAs(){ ... }
}
So that I can do the following later on:
void function( Dispatcher * disp ) {
// Works for Donut and Cake, but result will be a different Baked object
Baked b = disp->getStuffAs<Baked>();
// works if disp points to a DonutDispatcher
// fails if it is a CakeDispatcher
// can be compiling/linking time error or runtime error. I don't care
Frozen f = disp->getStuffAs<Frozen>();
}
Requirements/constraints:
All possible return types are not known beforehand. That's why I "need" templates.
Each class can provide just some return types.
Classes must have a common ancestor, so that I can store objects through a pointer to parent class and invoke functions through this pointer.
EDIT: I CAN'T use C++11 features, but I CAN use boost library.
Things I've thought about, but are not a solution:
Obviously, virtual template functions
Curiously Recurring Template Pattern: breaks the condition of common ancestor
Using some kind of traits class containing the functionality of children classes, but it does not work because a non-virtual implementation in the parent class does not have access to this information
I could maybe store some typeid info in the parent class, passed by children on construction. This makes possible for the non-virtual parent dispatching method to dynamic-cast itself to the children type... but it appears to be ugly as hell, and I don't know if this can cause some kind cycle-referencing problem.
class Dispatcher {
private:
typeid(?) childType;
public:
Dispatcher(typeid childT) : childType(childT) {}
// NOT VIRTUAL
template <class ReturnType>
ReturnType getStuffAs()
{
// or something equivalent to this cast, which I doubt is a correct expression
return dynamic_cast<childType *>(this)->childGetStuffAs<ReturnType>();
}
};
Then child classes would implement childGetStuffAs functions, which are not virtual too.
I've read like 5-10 related questions, but none of the provided solutions seems to fit this problem.
Can any of you come up with a better solution?
Is there a standard pattern/technique for solving this problem?
EDIT: The real problem
In the real problem, I have physical models with properties that can be represented in multiple ways: functions, matrices, probability distributions, polynomials, and some others (for example, a non-linear system can be represented as a function but not as a a matrix, while a linear system can be transformed to both).
There are also algorithms which can use those models indistinctly, but they could require specific representations for some model features. That's the reason for the "getStuffAs" function. The whole think is a bit complicated --too much to explain it here properly--, but I can guarantee that in this context the interface is well defined: input, computation and output.
My intention was to make this possible assuming that the number of possible representations is fully defined beforehand, and making it possible to transform the products to already existing types/classes that cannot be modified.
However, i'm starting to realize that this is, indeed, not possible in a simple way --I don't want to write a library just for this problem.
#include <cstdio>
// as a type identifier
struct stuff {
virtual void foo() {}
};
template <typename T>
struct stuff_inh : stuff {
};
struct Dispatcher {
template <typename T>
T* getStuffAs() {
return (T*)((getStuffAsImpl( new stuff_inh<T>() )));
}
virtual void* getStuffAsImpl(void*) = 0;
virtual void type() {printf("type::dispatcher\n");}
};
struct Cake : public Dispatcher {
void* getStuffAsImpl(void* p) {
stuff* s = static_cast<stuff*>(p);
printf("cake impl\n");
if (dynamic_cast<stuff_inh<Cake>*>(s) == NULL) {
throw "bad cast";
}
return (void*)(new Cake());
}
virtual void type() {printf("type::Cake\n");}
};
struct Rabbit : public Dispatcher {
void* getStuffAsImpl(void* p) {
stuff* s = static_cast<stuff*>(p);
printf("rabbit impl\n");
if (dynamic_cast<stuff_inh<Rabbit>*>(s) != NULL) {
return (void*)(new Rabbit());
}
else if (dynamic_cast<stuff_inh<Cake>*>(s) != NULL) {
return (void*)(new Cake());
}
else {
throw "bad cast";
}
}
virtual void type() {printf("type::Rabbit\n");}
};
void foo(Dispatcher* d) {
d->getStuffAs<Cake>()->type();
d->getStuffAs<Rabbit>()->type();
}
int main() {
Rabbit* r = new Rabbit;
foo(r);
Cake* c = new Cake;
foo(c);
}
I an not sure about the correctness of this ugly solution, may it be helpful for you. >_<
deletion of resource is not coded for a clearer look.
My solution is a combination of recurring template and diamond inheritance.
At least it's working. :)
#include <iostream>
class Dispatcher
{
public:
template<class T>
T getStuff()
{
return T();
}
};
template<class T>
class Stuffer : public Dispatcher
{
public:
template<class TT=T>
TT getStuff(){
return reinterpret_cast<TT>(this);
}
};
class Cake{
public:
Cake(){}
void print()
{
std::cout << "Cake" << std::endl;
}
};
class Recipe
{
public:
Recipe(){}
void print()
{
std::cout << "Recipe" << std::endl;
}
};
class CakeRecipe : public Stuffer<Cake>, public Stuffer< Recipe >
{
public:
};
int main()
{
Dispatcher* cr = reinterpret_cast<Dispatcher*>(new CakeRecipe());
cr->getStuff<Cake>().print();
cr->getStuff<Recipe>().print();
getchar();
return 1;
}
I have an abstract base class like so:
class AbstractBaseClass
{};
a templated concrete class that derives from it:
template<class T>
class ConcreteClass : public AbstractBaseClass
{
public:
ConcreteClass(T input) : data(input) {}
private:
T data;
};
AndI have a factory class that creates AbstractBaseClasses
class MyFactory
{
public:
boost::shared_ptr<AbstractBaseClass> CreateBlah();
boost::shared_ptr<AbstractBaseClass> CreateFoo();
template<class T>
boost::shared_ptr<AbstractBaseClass> Create(T input)
{
return boost::shared_ptr<AbstractBaseClass>(new ConcreteClass<T>(input));
}
};
The problem with this, is that now EVERYTHING that uses MyFactory has to include the entire implementation to ConcreteClass. Ideally, I want nothing but MyFactory to know about ConcreteClass.
Is there any way to architect this to achieve this goal? (Besides manually making a new Create function in MyFactory for every type I want instead of templating it).
you'll need to put the factory implementation into the implementation file (which you mentioned you'd like to avoid, but it is the lesser evil unless the interfaces are small, and/or your projects are small).
of course, there are a few other ways you could approach this, such as putting the implementation into base classes, and making derived bases factories, or using some other really weird template syntax to reduce instantiations in dependent translations. this really comes down to convenience and scale for your project. if you are working on one or more large projects, then full abstraction wrt instantiation will serve your needs best in the long run (assuming you need dynamic polymorphism and memory).
you may also try other approaches (such as overloading) to reduce errors by using type-safety.
the short answer is that you'll really need to abstract the interfaces/instantiation into one or multiple implementation files to remove header dependencies - very common idiom, and many ways to tackle it. you can over course further divide and use polymorphism for your factories as well.
you may also use template forward declarations to minimize the sets to the compilation unit. provided:
/** in MyIntermediateFactory.hpp */
class MyIntermediateFactory {
public:
static template<class T> boost::shared_ptr<T> Create(float);
};
/** in Concrete.hpp */
template<Concrete>
boost::shared_ptr<T> MyIntermediateFactory::Create<Concrete>(float arg) {
/* … */
}
using this you can select portions of programs/interfaces which you need in the library, then wrap it all up in a real Factory (for the build at hand). the linker/instantiation should fail along the way if you actually attempt to request a creation which is not visible.
there a lot of options, really - you need to figure out how big your scale is in order to determine what to abstract (or not). instantiation requires interface, to remove header dependencies, you'll have to abstract the instantiation someplace.
My approach to the same problem in the past was the creation of a set of concrete factories (one per type) that get registered in the global factory (for illustration purposes, indexing by object name):
class AbstractBaseClass;
class ConcreteFactory
{
public:
AbstractBaseClass * create();
};
class AbstractFactory
{
public:
void registerFactory( std::string const & name, std::shared_ptr<ConcreteFactory> const & f )
{
factory[ name ] = f; // check for collisions, complain if so ...
}
AbstractBaseClass * create( std::string const & name )
{
return factory[name]->create(); // check for existence before dereferencing...
}
private:
std::map<std::string, std::shared_ptr<ConcreteFactory> > factory;
};
I used this in a piece of code that was heavily templated to reduce compilation time. Each concrete factory and the class that it creates need only be in a single translation unit that registers the concrete factory. The rest of the code only need to use the common interface to AbstractBaseClass.
I realize I am answering this five years later. Maybe the language has grown a tad since then. I'd like to offer something that seems right, if I understand the question properly, if for no other point than to help others who might find this question and wonder what they could do.
factory.hpp
#include "base.hpp"
namespace tvr
{
namespace test
{
class factory
{
public:
typedef base::ptr Ptr;
enum eSpecial
{
eDerived
};
template<typename Type>
Ptr create()
{
Ptr result;
result.reset(new Type());
return result;
}
template<typename Type, typename DataType>
Ptr create(const DataType& data)
{
Ptr result;
result.reset(new Type(data));
return result;
}
template<typename Type, typename DataType>
Ptr create(const DataType& data, eSpecial tag)
{
Ptr result;
result.reset(new Type());
static_cast<Type*>(result.get())->set_item(data);
return result;
}
};
}
}
base.hpp
#include <memory>
namespace tvr
{
namespace test
{
class base
{
public:
typedef std::shared_ptr<base> ptr;
public:
base() {}
virtual ~base() {}
virtual void do_something() = 0;
};
}
}
some_class.hpp
#include <ostream>
namespace tvr
{
namespace test
{
struct some_class
{
};
}
}
std::ostream& operator<<(std::ostream& out, const tvr::test::some_class& item)
{
out << "This is just some class.";
return out;
}
template_derived.hpp
#include <iostream>
#include "base.hpp"
namespace tvr
{
namespace test
{
template<typename Type>
class template_derived : public base
{
public:
template_derived(){}
virtual ~template_derived(){}
virtual void do_something()
{
std::cout << "Doing something, like printing _item as \"" << _item << "\"." << std::endl;
}
void set_item(const Type data)
{
_item = data;
}
private:
Type _item;
};
}
}
and, finally, main.cpp
#include <vector>
#include "base.hpp"
#include "factory.hpp"
namespace tvr
{
namespace test
{
typedef std::vector<tvr::test::base::ptr> ptr_collection;
struct iterate_collection
{
void operator()(const ptr_collection& col)
{
for (ptr_collection::const_iterator iter = col.begin();
iter != col.end();
++iter)
{
iter->get()->do_something();
}
}
};
}
}
#include "template_derived.hpp"
#include "some_class.hpp"
namespace tvr
{
namespace test
{
inline int test()
{
ptr_collection items;
tvr::test::factory Factory;
typedef template_derived<unsigned int> UIntConcrete;
typedef template_derived<double> DoubleConcrete;
typedef template_derived<std::string> StringConcrete;
typedef template_derived<some_class> SomeClassConcrete;
items.push_back(Factory.create<SomeClassConcrete>(some_class(), tvr::test::factory::eDerived));
for (unsigned int i = 5; i < 7; ++i)
{
items.push_back(Factory.create<UIntConcrete>(i, tvr::test::factory::eDerived));
}
items.push_back(Factory.create<DoubleConcrete>(4.5, tvr::test::factory::eDerived));
items.push_back(Factory.create<StringConcrete>(std::string("Hi there!"), tvr::test::factory::eDerived));
iterate_collection DoThem;
DoThem(items);
return 0;
}
}
}
int main(int argc, const char* argv[])
{
tvr::test::test();
}
output
Doing something, like printing _item as "This is just some class.".
Doing something, like printing _item as "5".
Doing something, like printing _item as "6".
Doing something, like printing _item as "4.5".
Doing something, like printing _item as "Hi there!".
This uses a combination of templates, function overloading, and tagging through enums to help create a flexible factory class that doesn't require knowing much about the individual classes it instantiates, to include templated concrete classes as the OP asked about.
The 'eDerived' tag (in the form of an enum) tells the compiler to use the version of the factory's create function that takes a class like the template_derived class, which has a function that allows me to assign data to one of its members. As you can tell from the way I ordered the headers in main.cpp, the factory doesn't know anything about template_derived. Neither does the function calling the base class's virtual function (do_something). I think this is what the OP wanted, but without having to add a various create functions within every class that this factory might generate.
I also showed how one doesn't have to explicitly create functions for each class the factory should create. The factory's overloaded create functions can create anything derived from the base class that matches the appropriate signature.
I didn't do an extensive performance analysis on this code, but I did enough to see that the majority of the work happens in the streaming operator. This compiles in about 1 second on my 3.30Ghz quad core machine. You might need to experiment with more robust code to see how badly it might bog down the compiler, if much at all.
I've tested this code in VC++ 2015, although it probably works in other compilers pretty easily. If you want to copy this, you'll need to add your own guard headers. In any event, I hope this is useful.
You could use explicit template instanciation. Trying to call the factory method with a template parameter not explicit instanciated will give you a linker error. Note the explicit template instanciation in MyFactory.cpp
template AbstractBaseClass* MyFactory::Create(int input);
All put together looks like this (I removed shared_ptr for the sake of simplicity):
Main.cpp:
#include "AbstractBaseClass.h"
#include "MyFactory.h"
//we do not need to know nothing about concreteclass (neither MyFactory.h includes it)
int main()
{
MyFactory f;
AbstractBaseClass* ab = f.Create(10);
ab = f.Create(10.0f);
return 0;
}
MyFactory.h:
#include "AbstractBaseClass.h"
class MyFactory
{
public:
template<class T>
AbstractBaseClass* Create(T input);
};
MyFactory.cpp:
#include "MyFactory.h"
#include "ConcreteClass.h"
template<class T>
AbstractBaseClass* MyFactory::Create(T input) {
return new ConcreteClass<T>(input);
}
//explicit template instanciation
template AbstractBaseClass* MyFactory::Create(int input);
//you could use as well specialisation for certain types
template<>
AbstractBaseClass* MyFactory::Create(float input) {
return new ConcreteClass<float>(input);
}
AbstractBaseClass.h:
class AbstractBaseClass{};
ConcreteClass.h:
#include "AbstractBaseClass.h"
template<class T>
class ConcreteClass : public AbstractBaseClass
{
public:
ConcreteClass(T input) : data(input) {}
private:
T data;
};
You're looking for the "PIMPL" idiom. There's a good explanation at Herb Sutter's GOTW site
It can't be done because ConcreteClass is a template, that means you need the complete implementation available at compile time. Same reason why you can't precompile templates and have to write them all in header files instead.