boost::is_same with templated base class - c++

I'm puzzled by the following problem. I want to write some trait struct in order to test if a certain class is derived from another. This can be solved with boost::is_base_of<>. However, the base class I want to test against has a free undefined template parameter.
Here is some code example:
template<typename T> class Base {};
class IntDeriv : Base<int> {};
class Foo {};
template< class TestClass >
struct is_derived_from_Base {
// how to create something that does the following and forces the compiler to deduce T
static const bool value = boost::is_base_of< Base<T> , TestClass >::value;
};
int main() {
cout << is_derived_from_Base<Foo> << endl; // should print 0
cout << is_derived_from_Base<IntDeriv> << endl; // should print 1
}
The problem is how to deduce T for Base<T> inside is_base_of.
Is this possible at all? I smell some enable_if but I'm not sure how to put it together.

What you want is possible. The trick used is possible in C++03, but as you didn't specify I will give you the C++11 version (using decltype, not available in C++03):
template<class TestClass>
struct is_derived_from_Base
{
template<typename T>
static std::true_type inherited(Base<T>*);
static std::false_type inherited(void*);
static const bool value = decltype(inherited(new TestClass()))::value;
};
You can see a live version here.
So, how does it works ?
When the struct is instantiated and value is needed, the compiler will get the return type of inherited(new TestClass()). This will call the appropriate function: if TestClass inherits Base<T>, then TestClass* (returned by new) is castable to Base<T>*, T being automatically deduced by the compiler. The return type is std::true_type. If TestClass does not inherits Base<T>, then the other overload is choosen, and the return type is std::false_type. The rest is straightforward: std::true_type::value = true and std::false_type::value = false.
There are still some corner cases:
Using private inheritance results in a compile error. I do not know how to solve it, because I don't know the answer: if A privately inherits B, is A derived from B or not ? (in general, private inheritance is considered as an implementation inheritance). Also note that in this case, A* a = new B(); will not compile.
Using a private constructor prevents the previously explained trick from working correctly. It will result in a compile-time error. Since this defeats the whole point of this method, you will have to find another way for such classes.
Note you have to use it the following way: is_derived_from_Base<Foo>::value, not as you've written (is_derived_from_Base<Foo>).

Related

Make sure only Smartpointers are build

I want to make sure only smart pointers are build from my classes so i made all constructors protected.
To create objects i build this "Buildable"-Policy:
template <typename T>
class Buildable
{
public:
template<typename ...Args>
static QSharedPointer<T> buildObject(Args&&... all)
{
return QSharedPointer<T>( new T(std::forward<Args>(all)...) );
}
};
If i use this this policy in a base class, all goes well.
But when i use it in base and a derived class like this:
class A : public Buildable<A> {}
class B : A, public Buildable<B>{}
the compiler argues: Error: member 'buildObject' found in multiple base classes of different types
I don't know how to solve this problem. Any ideas?
Cause of the error
This is because the multiple inheritance here:
class B : A, public Buildable<B>{};
It causes class B to inherit from Buildable<A> and from Buildable<B> which both contain a buildObject() overload. Unfortunately, both overloads differs only by the return type. This is not allowed.
Design issue
Unfortunately, you can't avoid this unless you could smuggle an additional parameter to buildObject(), which could permit the compiler to use proper type derivation to resolve avoid ambiguity.
But do you really intend to have multiple inheritance in your design here ? If your classes would be polymorphic, couldn't you use a class B defined as follows:
class B : public A {}; // inherits from Buildable A
...
QSharedPointer<A> b = B::buildObject(); //
Alternative design
The alternative could be to put the building class at the bottom of the derivation, to avoid the conflicts. Make your constructors for classes A and B protected, and use this template class :
// (I used here shared_ptr instead of QSharedPointer for testing purpose)
template <typename T>
class Builder : public T
{
public:
Builder() = delete;
Builder (const Builder&) = delete;
template<typename ...Args>
static shared_ptr<T> buildObject(Args&&... all)
{
return make_shared<T>(std::forward<Args>(all)...) ;
}
};
class A { };
class B : public A {}; // Normal class hierarchy.
// can't be instantiated if ctor are protected.
shared_ptr<A> a = Builder<A>::buildObject();
shared_ptr<B> b = Builder<B>::buildObject();
One easy solution to the design problem is to make buildObject a freestanding function template, that you make a friend of each user class.
In order to simplify friend declarations you may want to put that function template in a class.
Then it's very much like your existing code, except there's no inheritance from the factory class:
#include <memory> // std::shared_ptr
#include <utility> // std::forward
namespace my{
using std::forward;
using std::shared_ptr;
template< class Class >
struct Make_
{
template< class... Args >
static auto instance( Args&&... args )
-> shared_ptr<Class>
{ return shared_ptr<Class>( new Class( forward<Args>( args )... ) ); }
};
class A
{
template< class > friend struct Make_;
protected:
A( int ) {}
};
class B
: public A
{
template< class > friend struct Make_;
protected:
B( int x ): A( x ) {}
};
} // namespace my
auto main() -> int
{
using namespace my;
auto p = Make_<B>::instance( 42 );
}
General solutions to the immediate technical problem of providing a covariant function without repeating its definition, include:
A macro (that expands to the function definition).
This is what I recommend, if you feel that it absolutely has to be a member function. It's one of the few legitimate uses of macros.
Middle-man inheritance.
Essentially instead of inheriting directly from a Base and also from a mixin, you inherit from the mixin and ask it to inherit from Base. You need to forward constructor arguments from the mixin.
Dominance in virtual inheritance hierarchy.
A really ugly and complex solution. Don't go there. But it's a technical possibility.
Finally there is non-solution of using a function that returns a (smart) pointer to base class. Where the client code has to cast it down. It's really ungood in its own way, but I mention it for completeness.
You could inherit from QEnableSharedFromThis (see here for further details).
As an example:
class C: public QEnableSharedFromThis<C> {
C() = default;
// all the other constructors
public:
template<typename ...Args>
static QSharedPointer<C> create(Args&&... all) {
// refers one of the available constructors
return QSharedPointer<C>(new C{std::forward<Args>(all)...});
}
QSharedPointer<C> getSharedFromThis() {
return sharedFromThis();
}
};
You can use it as a base class for your hierarchy.

Static assertion that a base pointer "equals" a derived pointer

Suppose I have a polymorphic hierarchy of classes with a common base:
struct Base { ~virtual Base() = default; };
I have inherited a large codebase which contains a long series of accessor functions (one for each derived type) that obtain a derived pointer via reinterpret_cast:
Derived * Get() // Derived inherits from Base
{
Base * b = lookup_derived();
return reinterpret_cast<Derived *>(b);
}
Obviously the code should be using static_cast or dynamic_cast (depending on whether the base is virtual). However, because this translation unit is large and the definitions of all the derived classes are jointly huge, the TU does not contain the definition of Derived, but only its declaration.
I would like to make this code more robust by adding to each derived class definition a static assertion that this reinterpret cast will produce the correct result. Essentially, I want something like this:
struct Derived : Base
{
static_assert(static_cast<Derived *>(std::declval<Base *>()) ==
reinterpret_cast<Derived *>(std::declval<Base *>()));
// ...
};
This constructions does not work of course since declval must not be evaluated, and the result of a reinterpret cast is not a constant expression. Is there any standard C++ mechanism to perform such a test statically? (The alternative would be a runtime check on this in the class constructor.)
Edit: Based on Aaron's post, I struck me that the question could be phrased entirely without reinterpret_casts:
static_cast<void *>(std::declval<Derived *>()) ==
static_cast<void *>(static_cast<Base *>(std::declval<Derived *>()))
I'm not sure if this will be good enough for the setup you have, but this code on ideone works for me (clang 3.5.0 and g++ 4.9.3).
Updated to cast in the other direction, i,e. Derived*-to-Base*, to more closely match the question. And also updated to use static_cast<void*> explicitly instead of C-style casting and reinterpret_cast .
template<typename D, typename B>
struct CheckCasting {
static D d_static;
constexpr
static B* bp = &d_static; // the original object is D,
// that allows us to static_cast both ways
static
constexpr bool static_equals_reinterpret() {
return static_cast<void*>(static_cast<D*>(bp))
== static_cast<void*>( bp );
}
};
struct Base {
constexpr Base() : i(0) {}
int i;
};
struct derived_with_virtual : public Base {
derived_with_virtual() {}
virtual void foo() { }
};
struct without_virtual : public Base {
without_virtual() {}
};
static_assert( ! CheckCasting<derived_with_virtual, Base> :: static_equals_reinterpret() ,"");
static_assert( CheckCasting<without_virtual , Base> :: static_equals_reinterpret() ,"");
A few comments:
I tried to replace the cast to void* with reinterpret_cast, but clang didn't like that. "note: reinterpret_cast is not allowed in a constant expression".
I tried moving the static_assert inside the Derived class without success.
This requires statically allocating an object for each Derived class.

Access protected base class type for other base class template initialization

I have a piece of code where I make use of the BaseFromMember idiom to be able to create a proper inheritance relationship for the class I am actually interested in (called Derived). I stumpled upon the fact that it is not possible to access protected (or private) base class types before the body of the derived class. See my code below:
struct BaseFromMember
{
//protected: // comment/uncomment this line
using T = int; // using declaration/typedef
protected:
BaseFromMember()
: t_(1)
{}
const T& t() const { return t_; }
private:
const T t_;
};
template<class T>
class Base
{
public:
Base(const T& t)
{}
};
class Derived
: private BaseFromMember // private, protected, public doesn't matter here
, public Base<typename BaseFromMember::T> // this does not work for protected type T
{
using T = typename BaseFromMember::T; // works
public:
Derived()
: BaseFromMember()
, Base(BaseFromMember::t())
{}
};
int main()
{
Derived d;
}
As expected, the problem does not depend on the fact which modifier is used to derive Derived from BaseFromMember.
However, Base can only be initialized if the using declaration in BaseFromMember is public, otherwise I get an error with both, gcc (4.8.2) and clang (3.4-1). I consider this behaviour unexpected, especially because typename BaseFromMember::T is accessible in Derived's body.
I was not able to find any related topic on stackoverflow. I found this thread though, although I am not certain if it addresses the same issue.
Question: Did I do something wrong or do I assume something that should not be assumed? Or this is maybe just a compiler bug?
Note: Even more disturbing to me is the fact that the keyword typename does not seem to have any effect when establishing the inheritance of Derived. Maybe I just did something very silly?
Note: I am not sure if the term initalization is correct in this context as used in the title of this thread. Please let me know if another term would be more appropriate. Of course, I would also like to know if any other terms that I use are inappropriate :).
This is not an answer.
A first step might be the reduction of your code to something shorter. I believe this code still exhibits the behaviour you describe:
class A {
protected:
typedef int T;
};
template <typename T> class B {};
class C : public A, B<typename A::T> {};
Indeed, this fails to compile with clang 3.4.1 and gcc 4.8.2, whereas earlier version (4.5,4.6,4.7) happily accept it (I ran each compiler in C++0x mode).

How to detect template parameters of base classes at compile time (for errors)?

I've been using the Curiously recurring template pattern The general code looks like this:
template <typename T> void genericFunction(T &);
template <typename T> struct Functionality {
void genericMethod() {
genericFunction(*((T *)this)) ;
}
};
struct Klass : public Functionality<Klass> {};
void main() {
Klass obj ;
obj.genericMethod();
}
template <> void genericFunction<Klass>(Klass &obj) {
//do stuff with Klass &obj here
}
I ran into an error today which cost me about 90 minutes of hair-pulling fustration, this error was caused by using an incorrect template parameter for my base class inheritance declaration, somewhat like so:
struct Klass : public Functionality<SomeOtherKlass> {}; //SomeOtherKlass wrong!!!
I'd like to enhance my code so that this mismatch between the derived class and the base class template parameter is detected (runtime, compile time, anytime :) ), is this even possible?, thanks.
You could assert the relation in e.g. genericMethod() using Boost or C++11 features:
BOOST_STATIC_ASSERT(( boost::is_base_of<Functionality<T>, T>::value ));
... although that is assuming that the other class doesn't derive from Functionality<T> as well.
An alternative could be to assert the relation at runtime in test-builds:
template <typename T> struct Functionality {
#ifdef TEST_BUILD
virtual ~Functionality() {}
#endif
void genericMethod() {
#ifdef TEST_BUILD
assert(dynamic_cast<T*>(this));
#endif
genericFunction(*((T *)this)) ;
}
};
Note that the test won't work inside constructors and destructors
In C++11, the following should work:
template<typename T> class Base
{
friend T; // allowed in C++11
private:
~Base() {}
public:
// ...
};
class Derived: public Base<Derived> {}; // OK
class WronglyDerived: public Base<Derived> {}; // Error: destructor of base class is private
You could use a dynamic_cast, which will return null if you have the wrong parameter type. (You'll need at least one virtual function in the base for this to work - the destructor, say.)
If you're worried about efficiency, boost has a polymorphic_cast which does a dynamic cast in debug mode but a static cast for production.
(And in any case it would be nice to avoid the use of the C-style cast.)
Suppose you add a templated constructor to the base that takes a pointer to arbitrary type;
template<class U> Functionality(U *) { ... }
Then each derived class's constructor can pass its this pointer to the constructor, and in the body of the constructor you just static assert that U and T are the same type.
The constructor parameter is never actually used so should be optimised out entirely. And if this is the only base class constructor you can't forget to call it. The only problem would be if you passed something other than this.
The most tangible suggestion thus far is to use dynamic_cast to expose malformed inheritance declarations in the Base class constructor, like so:
#include <iostream>
template <typename T> struct Base {
Base() {
std::cout<<dynamic_cast<T *> (this)<<std::endl;
}
virtual void iampolymorphic(){}
};
struct Decoy {} ;
struct Pass : public Base<Pass>{}; //correct
struct Fail : public Base<Decoy>{}; //incorrect
int main() {
Pass p ;
Fail f ;
return 1 ;
}
This code compiles on g++ 4.6.1, Amd64 Xubuntu 11.10. The output for both dynamic cast operations is a null pointer. Comments, criticisms and observations are welcomed.

Detecting Inheritance during compile time

I am unable to figure out why this code is returning false. I had the first version of partial specialization. It did not work, I tried with the second version. It did not work either.
UPDATE: I wanted to check if "Derived" is publicly derived from "Base".
UPDATE:
template<typename TDerived, typename TBase>
struct Derived_From
{
public:
static void constraints(TBase*, TDerived* ptr) { TBase* b = ptr; ignore(b); }
Derived_From() { void (*p)(TBase*, TDerived*) = constraints; ignore(p);}
};
I found the above code snippet in Strostrup's homepage. But, it does not let the code compile if the derived class is not publicly derived from Base.
template<class TBase, class TDerived>
struct IsDerived
{
public:
enum { isDerived = false };
};
template<class TBase>
struct IsDerived<TBase, TBase>
{
public:
enum { isDerived = true };
};
template<class TBase>
struct IsDerived<TBase&, TBase&>
{
public:
enum { isDerived = true };
};
int main()
{
cout << ((IsDerived<Base&, Derived&>::isDerived) ? "true" : "false")
<< endl;
cout << ((IsDerived<const Derived*, const Base*>::isDerived) ?
"true" : "false") << endl;
}
I always just use pointer initialization for this. Pointers implicitly convert only to a supertype (could be identity conversion or public base class), so it won't compile unless that relationship exists (and in the right direction).
e.g.
Parent* p = (Possibly_Derived*)0;
Oh wait, you're not wanting compilation to fail, but to set a variable? Here:
template<typename TParent>
bool is_derived_from( TParent* ) { return true; }
template<typename TParent>
bool is_derived_from( void* ) { return false; }
cout << is_derived_from<Parent>( (Possibly_Derived*)0 );
Here's a demo: http://ideone.com/0ShRF
Check out boost type traits, specifically the is_base_of template.
Firstly, I assume you want a generic method to work for any classes, without modifying or adding any function to the class. I think this template method cannot work. A derived class is not equal to the base class, and unless the two classes are EQUAL, the specialized struct will not be instantiated. Similarly, pointer to derived class is not equal to pointer to base class.
I assume you already know that people regularly use virtual functions to check if the "object" is of base class or derived class.
(Note that I am not saying what you want cannot be done - just that the results you are seeing are expected and the template approach will not work).
If I am right, you are calling the Template with 2 different Parameter types..
(IsDerived<Base&, Derived&>::isDerived)
Thus it will invoke
struct IsDerived
{
public:
enum { isDerived = false };
};
and this is why IsDerived<Base&, Derived&>::isDerived as well as IsDerived<const Derived*, const Base*>::isDerived is false.
calls like (IsDerived<Base&, Base&>::isDerived) will return True.
I wanted to check if "Derived" is
publicly derived from "Base".
I am not aware of Template based solution, and will keep a eye on this thread. but i usually exploit dynamic_cast to do this job, if ever needed.
If dynamic_cast cannot cast a pointer because it is not a complete object of the required class, it returns a null pointer to indicate the failure.
If dynamic_cast is used to convert to a reference type and the conversion is not possible, an exception of type bad_cast is thrown instead.