I would like to define as class X with a static method:
class X
{
static string get_type () {return "X";}
//other virtual methods
}
I would like to force classes which inherit from X to redefine the get_type() method
and return strings different from "X" (I am happy if they just redefine get_type for now).
How do I do this? I know that I cannot have virtual static methods.
Edit: The question is not about the type_id, but in general about a static method that
should be overriden. For example
class X {
static int getid() {return 1;}
}
template<int id>
class X {
public:
static int getid() { return id; }
};
class Y : public X<2> {
};
You haven't overridden the method, but you've forced every subclass to provide an ID. Caveat: I haven't tried this, there might be some subtle reason why it wouldn't work.
If I'm not mistaken, to call the static method, you have to invoke the method by specifying the exact name of the class, e.g X::get_type();, DerivedClass::get_type() etc and in any case, if called on an object, the dynamic type of the object is not taken into account. So at least in the particular case, it will probably only be useful in a templated context when you are not expecting polymorphic behavior.
However, I don't see why it shouldn't be possible to force each interesting class (inherited or not, since "compile-time polymorphism" doesn't care) to provide this functionality with templates. In the following case, you must specialize the get_type function or you'll have a compile-time error:
#include <string>
struct X {};
struct Derived: X {};
template <class T> std::string get_type() {
static_assert(sizeof(T) == 0, "get_type not specialized for given type");
return std::string();
}
template <> std::string get_type<X>() {
return "X";
}
int main() {
get_type<X>();
get_type<Derived>(); //error
}
(static_assert is C++0x, otherwise use your favourite implementation, e.g BOOST_STATIC_ASSERT. And if you feel bad about specializing functions, specialize a struct instead. And if you want to force an error if someone accidentally tries to specialize it for types not derived from X, then that should also be possible with type_traits.)
I'd say you know the why but just in case here's a good explanation:
http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlcpp8l.doc/language/ref/cplr139.htm
It looks like your going to have to design your way out of this. Perhaps a virtual function that wraps a Singleton?
Don't do that, use typeid instead.
To make a long story short, you can't do it. The only way to require a derived class to override a base class function is to make it a pure virtual (which can't be static).
You can't do this for a number of reasons. You can't define the function in X and have it be pure virtual. You can't have virtual static functions at all.
Why must they be static?
Here you go
class X
{
static string get_type() {return "X"; }
};
class Y : public X
{
static string get_type() {return "Y"; }
};
The code above does exactly what you requested: the derived class redefines get_type and returns a different string. If this is not what you want, you have to explain why. You have to explain what is it you are trying to do and what behavior you expect from that static method. If is absolutely unclear form your original question.
You mention a few places about guaranteeing that the child types yield unique values for your function. This is, as others have said, impossible at compile time [at least, without the use of templates, which might or might not be acceptable]. But if you delay it until runtime, you can maybe pull something similar off.
class Base {
static std::vector<std::pair<const std::type_info*, int> > datas;
typedef std::vector<std::pair<const std::type_info*, int> >::iterator iterator;
public:
virtual ~Base() { }
int Data() const {
const std::type_info& info = typeid(*this);
for(iterator i = datas.begin(); i != datas.end(); ++i)
if(*(i->first) == info) return i->second;
throw "Unregistered Type";
}
static bool RegisterClass(const Base& p, int data) {
const std::type_info& info = typeid(p);
for(iterator i = datas.begin(); i != datas.end(); ++i) {
if(i->second == data) {
if(*(i->first) != info) throw "Duplicate Data";
return true;
}
if(*(i->first) == info) throw "Reregistering";
}
datas.push_back(std::make_pair(&info, data));
return true;
}
};
std::vector<std::pair<const std::type_info*, int> > Base::datas;
class Derived : public Base { };
const DerivedRegisterFlag = Base::RegisterClass(Derived(), 10);
class OtherDerived : public Base { };
const OtherDerivedRegisterFlag = Base::RegisterClass(OtherDerived(), 10); //exception
Caveats: This is completely untested. The exceptions would get thrown before entering main if you do it this way. You could move the registration into constructors, and accept the per-instance overhead of registration checking if you'd rather.
I chose an unordered vector for simplicity; I'm not sure if type_info::before provides the necessary semantics to be used as a predicate for a map, and presumably you won't have so many derived classes that a linear search would be problematic anyhow. I store a pointer because you can't copy type_info objects directly. This is mostly safe, since the lifetime of the object returned by typeid is the entire program. There might be issues when the program is shutting down, I'm not sure.
I made no attempt to protect against static order of initialization errors. As written, this will fail at some point.
Finally, no it isn't static, but "static" and "virtual" don't really make sense together anyhow. If you don't have an instance of the type to act on, then how do you know which overwritten method to chose? There are a few cases with templates where you might legitimately want to call a static method without an actual object, but that's not likely to be common.
*edit: Also, I'm not sure how this interacts with dynamically linked libraries and the like. My suspicion is that RTTI is unreliable in those situations, so obviously this is similarly unreliable.
Use Delphi, it supports virtual static members on classes. ;>
Apologies for resurrecting this thread, but I've just encountered this moral crisis as well. This is a very bold and possibly foolish statement to make, but I wholeheartedly disagree with what most people are saying about static virtual not making any sense. This dilemma stems from how static members are commonly used versus what they're actually doing underneath.
People often express facts using static classes and/or members - something that is true for all instances if instances are relevant, or simply facts about the world in the case of static classes. Suppose you're modelling a Philosophy class. You might define abstract class Theory to represent a theory which is to be taught, then inherit from Theory in TheoryOfSelf, TheoryOfMind and so on. To teach a Theory, you'd really want a method called express() which expresses a theory using a particular turn of phrase appropriate to the audience. One would assume that any inheriting class should expose an identical method express(). If I were able to, I would model this relationship using static virtual Theory.express() - it is both a statement of fact transcending the concept of instances (therefore static) and nonspecific, requiring a specific implementation by each type of theory (therefore virtual).
I completely agree however with people justifying the prohibition on the grounds of what static is actually doing - it makes perfect sense in terms of coding principles, the issue arises from the customary ways people commonly model the real world.
The best resolution to this problem I've been able to think of is to model Theory as a singleton instead - there may be an instance of a theory, but there's only ever one of them. If you want an alternative, it's a different type, so create a new derived class. To me this approach just seems arbitrary and introduces unnecessary noise.
Related
Background:
I've inherited a large system that makes use of templates to store meta data about classes, that may have colored some of the assumptions inherent in this question.
I'm making use of a template registration system that is partially based on an answer found here: Is there a way to instantiate objects from a string holding their class name? . Macros are a no go in my system, as is the use of boost (or really any third party API).
Question:
Can I have templates that behave differently based on whether the input type is abstract versus concrete?
I'm looking for something like this (Code used here directly copied from the accepted answer in the linked question):
struct BaseFactory {
typedef std::map<std::string, Base*(*)()> map_type;
static Base * createInstance(std::string const& s) {
map_type::iterator it = getMap()->find(s);
if(it == getMap()->end())
return 0;
return it->second();
}
protected:
static map_type * getMap() {
// never delete'ed. (exist until program termination)
// because we can't guarantee correct destruction order
if(!map) { map = new map_type; }
return map;
}
private:
static map_type * map;
};
template<typename T>
struct DerivedRegister : BaseFactory {
DerivedRegister(std::string const& s) {
getMap()->insert(std::make_pair(s, &createT<T>));
}
};
// in derivedb.hpp
class DerivedB {
...;
private:
static DerivedRegister<DerivedB> reg;
};
// in derivedb.cpp:
DerivedRegister<DerivedB> DerivedB::reg("DerivedB");
Except that I would like DerivedRegister to behave differently based on whether T is abstract versus concrete. In the case where T is abstract, I would expect DerivedRegister to not register the type with the map.
As I mentioned in the background, I've already inherited an existing system which already exists on the class hierarchy (abstract or concrete). It was trivial to modify this existing system to add the map registration; however, the abstract classes are causing problems since calling new on them isn't valid.
Adding additional layers of inheritance and templating between BaseFactory and DerivedRegister wouldn't be a problem; however, DerivedRegister already exists on every class and I can't change that.
I recognize that I could just add a unique registration system independent of the existing template classes and only add it to the concrete classes. I'm specifically asking if there is a solution where I can avoid that in C++11 without using third party libraries (lots of restrictions I know...).
Use std::is_abstract:
If T is an abstract class (that is, a non-union class that declares or inherits at least one pure virtual function), provides the member constant value equal to true. For any other type, value is false.
I'm in a situation where I have a class, let's call it Generic. This class has members and attributes, and I plan to use it in a std::vector<Generic> or similar, processing several instances of this class.
Also, I want to specialize this class, the only difference between the generic and specialized objects would be a private method, which does not access any member of the class (but is called by other methods). My first idea was to simply declare it virtual and overload it in specialized classes like this:
class Generic
{
// all other members and attributes
private:
virtual float specialFunc(float x) const =0;
};
class Specialized_one : public Generic
{
private:
virtual float specialFunc(float x) const{ return x;}
};
class Specialized_two : public Generic
{
private:
virtual float specialFunc(float x) const{ return 2*x; }
}
And thus I guess I would have to use a std::vector<Generic*>, and create and destroy the objects dynamically.
A friend suggested me using a std::function<> attribute for my Generic class, and give the specialFunc as an argument to the constructor but I am not sure how to do it properly.
What would be the advantages and drawbacks of these two approaches, and are there other (better ?) ways to do the same thing ? I'm quite curious about it.
For the details, the specialization of each object I instantiate would be determined at runtime, depending on user input. And I might end up with a lot of these objects (not yet sure how many), so I would like to avoid any unnecessary overhead.
virtual functions and overloading model an is-a relationship while std::function models a has-a relationship.
Which one to use depends on your specific use case.
Using std::function is perhaps more flexible as you can easily modify the functionality without introducing new types.
Performance should not be the main decision point here unless this code is provably (i.e. you measured it) the tight loop bottleneck in your program.
First of all, let's throw performance out the window.
If you use virtual functions, as you stated, you may end up with a lot of classes with the same interface:
class generic {
virtual f(float x);
};
class spec1 : public generic {
virtual f(float x);
};
class spec2 : public generic {
virtual f(float x);
};
Using std::function<void(float)> as a member would allow you to avoid all the specializations:
class meaningful_class_name {
std::function<void(float)> f;
public:
meaningful_class_name(std::function<void(float)> const& p_f) : f(p_f) {}
};
In fact, if this is the ONLY thing you're using the class for, you might as well just remove it, and use a std::function<void(float)> at the level of the caller.
Advantages of std::function:
1) Less code (1 class for N functions, whereas the virtual method requires N classes for N functions. I'm making the assumption that this function is the only thing that's going to differ between classes).
2) Much more flexibility (You can pass in capturing lambdas that hold state if you want to).
3) If you write the class as a template, you could use it for all kinds of function signatures if needed.
Using std::function solves whatever problem you're attempting to tackle with virtual functions, and it seems to do it better. However, I'm not going to assert that std::function will always be better than a bunch of virtual functions in several classes. Sometimes, these functions have to be private and virtual because their implementation has nothing to do with any outside callers, so flexibility is NOT an advantage.
Disadvantages of std::function:
1) I was about to write that you can't access the private members of the generic class, but then I realized that you can modify the std::function in the class itself with a capturing lambda that holds this. Given the way you outlined the class however, this shouldn't be a problem since it seems to be oblivious to any sort of internal state.
What would be the advantages and drawbacks of these two approaches, and are there other (better ?) ways to do the same thing ?
The issue I can see is "how do you want your class defined?" (as in, what is the public interface?)
Consider creating an API like this:
class Generic
{
// all other members and attributes
explicit Generic(std::function<float(float)> specialFunc);
};
Now, you can create any instance of Generic, without care. If you have no idea what you will place in specialFunc, this is the best alternative ("you have no idea" means that clients of your code may decide in one month to place a function from another library there, an identical function ("receive x, return x"), accessing some database for the value, passing a stateful functor into your function, or whatever else).
Also, if the specialFunc can change for an existing instance (i.e. create instance with specialFunc, use it, change specialFunc, use it again, etc) you should use this variant.
This variant may be imposed on your code base by other constraints. (for example, if want to avoid making Generic virtual, or if you need it to be final for other reasons).
If (on the other hand) your specialFunc can only be a choice from a limited number of implementations, and client code cannot decide later they want something else - i.e. you only have identical function and doubling the value - like in your example - then you should rely on specializations, like in the code in your question.
TLDR: Decide based on the usage scenarios of your class.
Edit: regarding beter (or at least alternative) ways to do this ... You could inject the specialFunc in your class on an "per needed" basis:
That is, instead of this:
class Generic
{
public:
Generic(std::function<float(float> f) : specialFunc{f} {}
void fancy_computation2() { 2 * specialFunc(2.); }
void fancy_computation4() { 4 * specialFunc(4.); }
private:
std::function<float(float> specialFunc;
};
You could write this:
class Generic
{
public:
Generic() {}
void fancy_computation2(std::function<float(float> f) { 2 * f(2.); }
void fancy_computation4(std::function<float(float> f) { 4 * f(4.); }
private:
};
This offers you more flexibility (you can use different special functions with single instance), at the cost of more complicated client code. This may also be a level of flexibility that you do not want (too much).
In C# I can define this:
public interface BaseObject
{
int GetValue();
}
public class Test<T> where T : BaseClass
{
T BaseObject;
}
which means I know that I can alwaysa call BaseObject.GetValue() / BaseObject->GetValue(); because I know that the baseobject has this method.
Is there a similiar way to do this in C++? So that I can define an interface that multiple classes can inherit and a class that can take advantage of this.
Templates, which are even more powerful than C# generics (not to say they are necessarily better, just different).
template<class T>
class foo
{
public:
int whatever()
{
return obj.GetValue();
}
private:
T obj;
};
A separate class is created for each template argument you use. If you provide a template type which would result in an error you will know at compile time.
You're asking about C++ concepts, a way to specify requirements for template parameters. They were proposed during the work on C++11, but proved complicated enough that they weren't done in time. But they've just been delayed, not forgotten.
In the meantime, duck typing remains very powerful, and it will catch when you pass a template parameter that doesn't have the required interface. It just won't report the problem as neatly.
As a workaround, a simple way to check the constraint you showed takes advantage of the fact that pointer conversions are implicit only when upcasting:
public class Test<T> where T : BaseClass
{
static T* enforcement_helper = 0;
static BaseClass* enforce_inheritance_constraint = enforcement_helper;
};
Depending on how new your compiler is, you may need to put those lines inside a special member function (destructor is good, because it's almost always processed).
But you should only check constraints in order to improve error messages (by causing the failure in a clearly commented section of code). C++ templates are duck typed, and they will work with any template parameters that provide the required operations. No formal "interface" is required.
There are many reasons not to use typeid. Other than for using members of type_info (implementation defined behavior), it is usually (always?) possible to provide similar functionality using other C++ language features, eg: overloading, virtual functions etc.
So, excluding usage that relies on the implementation defined behavior, does anybody have a real world example where typeid is the best solution?
So, excluding usage that relies on the implementation defined behavior, does anybody have a real world example where typeid is the best solution?
I sometimes use it in debug outputs, to verify that a template argument passed to my function is indeed of a given type. This makes sense in my case since the actual template argument passed to my function is generated by a specialised metafunction and I want to make sure that the right metafunction is used.
boost::any uses typeid to implement any_cast.
template<typename T> any_cast(const any& other) {
if(typeid(T) != other.type()) throw bad_any_cast();
//...actual cast here...
}
You can't be sure T is polymorphic, so dynamic_cast is out of the question, and the enclosed type within the boost::any call is lost by now, so none of the other casts can provide any sort of type safety.
When implementing multimethods (or multiple dispatch), where the actual call is chosen from e.g. a map, using std::type_info* as a key.
Write a dynamic tree where you can on the runtime modify structure of the tree where there are different types in each link, it'll need typeid. dynamic_cast is not enough.
Edit: Here's some details:
class I {
public:
virtual std::string type() const=0;
virtual void *value() const=0;
};
template<class T>
class Impl : public I
{
public:
Impl(T t) : t(t) { }
std::string type() const { return typeid(T).name(); }
void *value() const { return &t; }
private:
T t;
};
And then build a tree out of these:
template<class Node, class Link>
class Tree { };
With link type being the I* interface... Since the above works for any values of type T1,T2,T3,T4, we could also with similar classes for any functions T->T1, T->T2, T->T3, T->T4, and use that function type as the Node of the tree. Now you have proper expressions described in dynamic tree.
You can use typeid to compare the actual types of two objects. Could be useful if you want to check equality of two objects, and first make sure they are of the exact same type (though I must say I haven't seen this done a lot, so there might be a good reason why this is not a good idea...).
I use it to probe the class type of the exception in my catch all handler.
// fudge vtable existence (thrown exceptions must have one)
class StubException
{
virtual ~StubException();
};
.....
catch(...)
{
StubException *e = getExceptionObject(); // compiler/rt specific
std::string s = typeid(e).name();
...
throw;
}
The function getExceptionObject() is part of a small utility library I wrong to access additional information about exceptions. It comes in very handy when a function throws an exception I should be catch but don't. It has definitely saved a lot of frustration over the years since I immediately know the type of exception that needs coverage.
I have an interesting problem. Consider this class hierachy:
class Base
{
public:
virtual float GetMember( void ) const =0;
virtual void SetMember( float p ) =0;
};
class ConcreteFoo : public Base
{
public:
ConcreteFoo( "foo specific stuff here" );
virtual float GetMember( void ) const;
virtual void SetMember( float p );
// the problem
void foo_specific_method( "arbitrary parameters" );
};
Base* DynamicFactory::NewBase( std::string drawable_name );
// it would be used like this
Base* foo = dynamic_factory.NewBase("foo");
I've left out the DynamicFactory definition and how Builders are
registered with it. The Builder objects are associated with a name
and will allocate a concrete implementation of Base. The actual
implementation is a bit more complex with shared_ptr to handle memory
reclaimation, but they are not important to my problem.
ConcreteFoo has class specific method. But since the concrete instances
are create in the dynamic factory the concrete classes are not known or
accessible, they may only be declared in a source file. How can I
expose foo_specific_method to users of Base*?
I'm adding the solutions I've come up with as answers. I've named
them so you can easily reference them in your answers.
I'm not just looking for opinions on my original solutions, new ones
would be appreciated.
The cast would be faster than most other solutions, however:
in Base Class add:
void passthru( const string &concreteClassName, const string &functionname, vector<string*> args )
{
if( concreteClassName == className )
runPassThru( functionname, args );
}
private:
string className;
map<string, int> funcmap;
virtual void runPassThru( const string &functionname, vector<string*> args ) {}
in each derived class:
void runPassThru( const string &functionname, vector<string*> args )
{
switch( funcmap.get( functionname ))
{
case 1:
//verify args
// call function
break;
// etc..
}
}
// call in constructor
void registerFunctions()
{
funcmap.put( "functionName", id );
//etc.
}
The CrazyMetaType solution.
This solution is not well thought out. I was hoping someone might
have had experience with something similar. I saw this applied to the
problem of an unknown number of a known type. It was pretty slick. I
was thinking to apply it to an unkown number of unknown type***S***
The basic idea is the CrazyMetaType collects the parameters is type
safe way, then executing the concrete specific method.
class Base
{
...
virtual CrazyMetaType concrete_specific( int kind ) =0;
};
// used like this
foo->concrete_specific(foo_method_id) << "foo specific" << foo_specific;
My one worry with this solution is that CrazyMetaType is going to be
insanely complex to get this to work. I'm up to the task, but I
cannot count on future users to be up to be c++ experts just to add
one concrete specific method.
Add special functions to Base.
The simplest and most unacceptable solution is to add
foo_specific_method to Base. Then classes that don't
use it can just define it to be empty. This doesn't work because
users are allowed to registers their own Builders with the
dynamic_factory. The new classes may also have concrete class
specific methods.
In the spirit of this solution, is one slightly better. Add generic
functions to Base.
class Base
{
...
/// \return true if 'kind' supported
virtual bool concrete_specific( int kind, "foo specific parameters" );
};
The problem here is there maybe quite a few overloads of
concrete_specific for different parameter sets.
Just cast it.
When a foo specific method is needed, generally you know that the
Base* is actually a ConcreteFoo. So just ensure the definition of class
ConcreteFoo is accessible and:
ConcreteFoo* foo2 = dynamic_cast<ConcreteFoo*>(foo);
One of the reasons I don't like this solution is dynamic_casts are slow and
require RTTI.
The next step from this is to avoid dynamic_cast.
ConcreteFoo* foo_cast( Base* d )
{
if( d->id() == the_foo_id )
{
return static_cast<ConcreteFoo*>(d);
}
throw std::runtime_error("you're screwed");
}
This requires one more method in the Base class which is completely
acceptable, but it requires the id's be managed. That gets difficult
when users can register their own Builders with the dynamic factory.
I'm not too fond of any of the casting solutions as it requires the
user classes to be defined where the specialized methods are used.
But maybe I'm just being a scope nazi.
The cstdarg solution.
Bjarn Stroustrup said:
A well defined program needs at most few functions for which the
argument types are not completely specified. Overloaded functions and
functions using default arguments can be used to take care of type
checking in most cases when one would otherwise consider leaving
argument types unspecified. Only when both the number of arguments and
the type of arguments vary is the ellipsis necessary
class Base
{
...
/// \return true if 'kind' supported
virtual bool concrete_specific( int kind, ... ) =0;
};
The disadvantages here are:
almost no one knows how to use cstdarg correctly
it doesn't feel very c++-y
it's not typesafe.
Could you create other non-concrete subclasses of Base and then use multiple factory methods in DynamicFactory?
Your goal seems to be to subvert the point of subclassing. I'm really curious to know what you're doing that requires this approach.
If the concrete object has a class-specific method then it implies that you'd only be calling that method specifically when you're dealing with an instance of that class and not when you're dealing with the generic base class. Is this coming about b/c you're running a switch statement which is checking for object type?
I'd approach this from a different angle, using the "unacceptable" first solution but with no parameters, with the concrete objects having member variables that would store its state. Though i guess this would force you have a member associative array as part of the base class to avoid casting to set the state in the first place.
You might also want to try out the Decorator pattern.
You could do something akin to the CrazyMetaType or the cstdarg argument but simple and C++-ish. (Maybe this could be SaneMetaType.) Just define a base class for arguments to concrete_specific, and make people derive specific argument types from that. Something like
class ConcreteSpecificArgumentBase;
class Base
{
...
virtual void concrete_specific( ConcreteSpecificArgumentBase &argument ) =0;
};
Of course, you're going to need RTTI to sort things out inside each version of concrete_specific. But if ConcreteSpecificArgumentBase is well-designed, at least it will make calling concrete_specific fairly straightforward.
The weird part is that the users of your DynamicFactory receive a Base type, but needs to do specific stuff when it is a ConcreteFoo.
Maybe a factory should not be used.
Try to look at other dependency injection mechanisms like creating the ConcreteFoo yourself, pass a ConcreteFoo type pointer to those who need it, and a Base type pointer to the others.
The context seems to assume that the user will be working with your ConcreteType and know it is doing so.
In that case, it seems that you could have another method in your factory that returns ConcreteType*, if clients know they're dealing with concrete type and need to work at that level of abstraction.