I am trying to understand the following code. Derived is a derived structure from T and what does "," means and then Fallback {}
template <class T>
struct has_FlowTraits<T, true>
{
struct Fallback { bool flow; };
struct Derived : T, Fallback { }; //What does it means ?
template<typename C>
static char (&f(SameType<bool Fallback::*, &C::flow>*))[1];
template<typename C>
static char (&f(...))[2];
public:
static bool const value = sizeof(f<Derived>(0)) == 2;
};
It's an implementation of Member Detector Idiom. It uses SFINAE to check whether type T has got a member called flow.
Edit: The comma part you're asking about is multiple inheritance. Struct Derived is (publicly) inheriting from both T and Fallback.
It's just multiple inheritance. The following is a Derived that is derived from T (and provides no further definition):
struct Derived : T { };
And the following is a Derived that is derived from both T and Fallback:
struct Derived : T, Fallback { };
That is, Derived will inherit the members of T and the members of Fallback. In this case, since Derived is a struct, the inheritance is by default public inheritence.
It means:
inside the definition of has_FlowTraits struct, you also define a new struct which is called Derived.
You say that this struct Derived is inheriting the type T, and the type Fallback. ( If you look at the line before, the struct Fallback has just been defined).
the {} simply means that there are no more details of implementation. No more method or attribute definition is needed for this type to be useful.
The comma means it derives either publicly or privately (depending on whether the T or Fallback is a struct or class) from those two classes. The comma simply includes those classes as those from which Derive will derive.
Related
Compiling the following contrived example:
class Base
{};
class Derived : public Base
{};
template< typename T >
class A
{};
class B
{
public:
static void f( const A< Base >& ) {}
};
int main()
{
A< Base > tb;
A< Derived > td;
B::f( tb );
B::f( td );
return 0;
}
using g++-8 gives me the following error:
error: no matching function for call to 'B::f(A<Derived>&)'
B::f( td );
note: no known conversion for argument 1 from 'A<Derived>' to 'const A<Base>&'
Why?
Since Derived is-a Base and it doesn't override any of Base's stuff, why can't I give a Derived in the place of a Base in the templated function parameter?
It is true that Derived is derived from Base, but that doesn't mean that A<Derived> must therefore be derived from A<Base>. C++ templates don't work this way.
All that A<Derived> is, is a class, instantiated by the A template. You could've simply declared:
class A_Derived {
// ...
};
With the same members (if it had any), and pretty much got the same results. Same for A<Base>. With nothing else in the picture, the two classes have absolutely nothing to do with each other, whatsoever. You can draw a mental picture here, as if you made the following declarations:
class A_Derived {
};
and
class A_Base {
};
Which is pretty much what this is history. Do you see A_Derived being explicitly derived from A_Base here? Obviously not. If something expects a reference or a pointer to A_Base, you cannot give it A_Derived, because the two classes have absolutely nothing to do with each other. They are independent classes.
P.S. You could declare an explicit specialization of A<Derived> as being derived from A<Base>, if you so wish, but specialization is a completely different topic...
Template instances, like A<Base> and A<Derived>, are different types. In particular they do not have any inheritance relationship even if Base and Derived do.
There are quite a few ways you can make what you want work.
First, you could make A<Derived> explicitly derive from A<Base>, but that means adding a whole class definition.
template<>
class A<Derived> : public A<Base>
{};
Second, you can provide an implicit conversion from A<Derived> to A<Base> in the form of a constructor template. You can use std::enable_if and std::is_base_of to only allow A<T> where T is derived from Base, or directly std::is_same if you only want to consider this particular Derived type.
template<typename T>
class A
{
template<typename U, typename = std::enable_if_t<std::is_base_of_v<T, U>>>
A(A<U> const& other);
};
Third, you can provide an implicit conversion in the form of an operator template, in much the same way.
template<typename T>
class A
{
template<typename U, typename = std::enable_if_t<std::is_base_of_v<U, T>>>
operator U();
};
Fourth, you can make f a function template and restrict what types it takes.
template<typename T, typename = std::enable_if_t<std::is_base_of_v<Base, T>>>
static void f(A<T> const& a);
I have some code like this
class A : public b<T>
{
public:
typedef b<T> _baseclass; // why we need this declaration
};
What is the use of typedef inside the class?
Is the definition limited to this class only?
Shall we create this as static and use without crating an object of the class?
This member type will be available outside of the class definition too, which is convenient in template code. If you passed an A into a function template, or maybe some other classes that also have _baseclass member types, then you can use _baseclass to find out what the base is without needing to know exactly what the top-level type is.
Standard templates like std::vector and std::map have member types like value_type — these do not signify a base class but have a similar purpose, in that you can use value_type anywhere a container is used, no matter which container is used.
Swapping typedef to using (because I want to), here's an example:
// The class templates
template <typename T>
struct Base {};
struct A : Base<int>
{
using base_class = Base<int>;
};
struct B : Base<char>
{
using base_class = Base<char>;
};
struct C : Base<bool>
{
using base_class = Base<bool>;
};
// The example
template <typename T>
void foo()
{
// typename needed because base_class is a "dependent name"
// (just go with it)
typename T::base_class the_base;
// This line is to suppress "unused variable" warnings
(void)the_base;
}
int main()
{
foo<A>();
foo<B>();
foo<C>();
}
Though this particular program doesn't actually "do anything", it shows a function template foo that can "know" what the base class was in each case, without any further information about exactly what T is. And it'll work for any class to which you've added a base_class member type!
Is it possible to check if a member variable, a member function, or a type definition is declared in a given class?
Various questions on StackOverflow talk about checking if a given class merely contains a member, essentially using std::is_detected. But all these solutions detect the member also in derived classes, which may not declare the member themselves.
For example, the following doesn't compile.
#include <experimental/type_traits>
struct base
{
using type = std::true_type;
};
struct derived : public base { };
template<typename T>
using has_type_t = typename T::type;
template<typename T>
constexpr inline bool has_type_v =
std::experimental::is_detected<has_type_t, T>::value;
int main ()
{
static_assert (has_type_v<base>);
static_assert (!has_type_v<derived>);
}
Can any changes be made so that the two assertions hold? Or is reflection needed for that?
I don't see a way for type or static member, but for regular member, you can have distinguish base::m from derived::m:
template<typename T>
using has_m_t = decltype(&T::m);
template<typename T>
constexpr inline bool has_m_v =
std::experimental::is_detected_exact<int (T::*), has_m_t, T>::value;
And the test:
struct base { int m; };
struct derived : public base {};
struct without {};
static_assert( has_m_v<base>);
static_assert(!has_m_v<derived>);
static_assert(!has_m_v<without>);
Demo
I'm inclined to say no. Proving that is of course hard, but I can explain why I think so.
C++ is a compiled language. The compiler has an internal representation of types, which you can't access directly. The only way to access this internal representation is through the facilities of the language. Actual implementations can vary in the way they represent types internally, and often do have additional information to produce better error messages. But this is not exposed.
So yes, most compilers can enumerate base types, and know exactly where each member of a class came from. That's essential for good error messages. But you can't enumerate base classes at compile time, using only C++ templates.
You might think that for data members you could try tricks with addresses and offsets. That won't work, again because you need to know the size of all base classes - and you can't enumerate those.
You might also consider tricks in which you create further-derived helper classes. That's possible, but they suffer from the same problem. You can only derive from the given type, not from its parent(s). It's thus possible to create a child class, but not a sibling. And that child inherits from parent and grandparent alike. Even if you wrote using derived::type in the helper class, that would find base::type.
You can but with a limitation, your compiler must have an intrinsic that provides the list of base classes (GCC provides it).
If you can have access to such en intrinsic, the only difficulty is to check that member access through the derived is not actualy an access to a member of the base.
To check this, the idea is to use the 'ambiguous' access that happens when accessing a member declared in multiple bases of a derived class:
struct base
{
using type = std::true_type;
};
struct Derived1 : base{
};
struct Derived2 : base{
using type = std::true_type;
};
struct Test1: Derived1,base{};
struct Test2: Derived2,base{};
void g(){
Test1::type a;
Test2::type b;//Do not compile: 'type' is ambiguous
}
So you can generalize this trick this way:
template<class T,class Base>
struct MultiDer: T,Base{};
template<class T,class Base,class=void>
struct has_ambiguous_type
:std::true_type{};
template<class T,class Base>
struct has_ambiguous_type
<T,Base,std::void_t<typename MultiDer<T,Base>::type>>
:std::false_type{};
template<class T,class=void>
struct has_type
:std::false_type{};
template<class T>
struct has_type
<T,std::void_t<typename T::type>>
:std::true_type{};
template<class T,class...Bases>
constexpr inline auto has_type_declared_imp =
has_type<T>::value
//if any ambiguous access happens then T has 'type'
&& ( (has_ambiguous_type<T,Bases>::value || ...)
//or no ambiguity happened because none of the base has 'type'
|| (!has_type<Bases>::value && ...));
template<class T>
constexpr inline auto has_type_declared =
has_type_declared_imp<T,__direct_bases(T)...>;//GCC instrinsic
static_assert(has_type_declared<Derived2>);
static_assert(!has_type_declared<Derived1>);
The only problem is portability: your compiler must provides a mechanism to get access to the list of direct bases of a type. Here I have used the GCC's intrinsic __direct_bases.
Template methods allows to span a set of method instances for different static type of arguments. Automatic argument deduction avoids duplication of information.
We are faced with a situation in which the static type we would like to automatically deduce as a template argument is the type of the class instance itself. (On the call site, the type of the instance can be a more specialised type than the class in which the template method is declared.)
eg.
class Base
{
public:
template <class T_callingObject>
T_callingObject foo()
{
bar += 1;
// We have a strong guarantee on this cast only if T_callingObject
// is automatically deduced !
return static_cast<T_callingObject&>(*this);
}
private:
int bar;
};
class Derived : public Base
{
};
int main()
{
Base base;
Derived derived;
base = base.foo<Base>(); // we already know the type of base is Base
derived = derived.foo<Derived>(); // idem
}
The question is : Is there a way not to repeat the type of base and derived ?
Edit: CRTP on Base is not an option here, we need to have a common ancestor type.
This is generally addressed with CRTP (Curiously Recursive Template Pattern) by making Base a template itself:
template <typename D>
struct Base {
D& foo() { return static_cast<D&>(*this); }
};
and thus struct Derived: Base<Derived>.
The set of operations you can conduct on the D parameters is restricted (it is an incomplete time at the time Base<Derived> is instantiated), but in your simple case this works.
You are still left to wonder if someone will not inadvertently write struct Bar: Base<Foo> though, so this only reduces the problematic surface.
EDIT: if CRTP for Base is not allowed (which often happen), you can layer the abstractions:
struct Base { virtual ~Base() {} };
template <typename D>
struct BaseT: Base {
D& foo() { return static_cast<D&>(*this); }
};
struct Derived: BaseT<Derived> {};
Since in general if foo needs to know what D is, you no longer have a single unified type.
I'm trying to implement a kind of CRTP (if I well understand what it is) with multiple inheritance.
My main goal is to have a unified way to access list of instances of each subclass.
May problem seems to reside in the namespace utilization.
Here is the code of the simplest version :
http://ideone.com/rFab5
My real problem is more similar to :
http://ideone.com/U7cAf
I have an additional warning using clang++ :
test.cpp:28:63: warning: static data member specialization of 'instances' must originally be declared in namespace 'NS1'; accepted as a C++0x extension [-Wc++0x-extensions]
template <> std::list<NS1::Derived*> NS1::Base<NS1::Derived>::instances;
^
test.cpp:15:34: note: explicitly specialized declaration is here
static std::list<T*> instances;
Problem has been updated since it does not behave the same using namespaces.
Problem re-edited to post code on Ideone
The problem is that you've tried to define the list variable wrong. You need to provide a definition for Base, in general- you don't just define it for the one part that happens to be Derived's subclass, unless it's an explicit specialization.
template<typename T> std::list<T*> NS1::Base<T>::instances;
http://ideone.com/Vclac
Compiles with no errors. There are no intermediates or anything like that required.
Changing Base() and Intermediary() to Base<U>() and Intermediary<Derived> in the constructors makes the code OK for GCC.
There is no reason to change the definition of instances in the second case: the template is identical as the first situation.
Afaik, you got the following options.
First, if Intermediate is always templated on the derived type, you don't need a list for it, because it will never be the most derived type. If it could be templated on other types / not be derived, you can add a defaulted non-type bool template parameter like so:
template<bool, class A, class B>
struct select_base{
typedef A type;
};
template<class A, class B>
struct select_base<false,A,B>{
typedef B type;
};
template<class T, bool IsDerived = false>
class Intermediate
: public select_base<IsDerived,
Base<T>,
Base<Intermediate<T> >
>::type
{
// ...
};
// derived use
class Derived : public Intermediate<Derived, true>
{
// ...
};
// non-derived use:
Intermediate<int> im;
If the intermediate class is not templated and does not already derive from Base, you need to derive from Base again in the most derived class:
class Derived : public Intermediate, public Base<Derived>
{
// ...
};
The big problem comes when the intermediate also derives from Base but is not templated. You can add a defaulted derived type, but that would make the non-derived use a bit more ugly:
#include <type_traits> // C++0x, use std::
//#include <tr1/type_traits> // C++03, use std::tr1::
struct nil_base{};
template<class Derived = nil_base>
class Intermediate
: public select_base<std::is_same<Derived,nil_base>::value,
Base<Intermediate<Derived> >, //
Base<Derived>
>::type
{
// ...
};
// derived use now without boolean flag
class Derived : public Intermediate<Derived>
{
// ...
};
// non-derived use a bit uglier
Intermediate<> im;
// ^^ -- sadly needed
The following compiles OK with MinGW g++ 4.4.1, MSVC 10.0, and Comeau Online 4.3.10.1:
#include <list>
template <class T>
class Base
{
protected:
Base()
{
instances.push_back(static_cast<T*>(this));
}
private:
static std::list<T*> instances;
};
template <class U>
class Intermediary : public Base<U>
{
protected:
Intermediary()
:Base<U>()
{
}
};
class Derived : public Intermediary<Derived>
{
public:
Derived()
:Intermediary<Derived>()
{
}
};
template<class Derived> std::list<Derived*> Base<Derived>::instances;
int main()
{}
The instances definition is copied verbatim from your question.
I say as Isaac Newton, I frame no hypotheses!
Cheers & hth.,