How to find, from which template-layers is object composed of? - c++

How can I use templates, to find out, from which types is type composed of when using template layers?
Let's have
template <typename Super>
class A : public Super {};
template <typename Super>
class B : public Super {};
template <typename Super>
class C : public Super {};
class Blank{};
template <typename CombinedType>
void printTypeComponents(const CombinedType & t) { ... }
int main()
{
typedef A<B<C<Blank>>> ComposedType;
ComposedType ct;
printTypeComponents(ct);
typedef A<C<Blank>> ComposedType2;
ComposedType2 ct2;
printTypeComponents(ct2);
}
I am attaching my try, wrong of course (works only if object is composed from all tested types, since tested types actually exists), but you can easily see from it, what my aim is
#include <boost/type_traits/is_base_of.hpp>
#include <iostream>
template <typename Super>
class A : public Super
{
public:
typedef A<Super> AComponent;
};
template <typename Super>
class B : public Super
{
public:
typedef B<Super> BComponent;
};
template <typename Super>
class C : public Super
{
public:
typedef C<Super> CComponent;
};
class Blank{};
template <typename CombinedType>
void printTypeComponents(const CombinedType & t)
{
if(boost::is_base_of<Blank, CombinedType::AComponent>::value)
std::cout << "composed of A \n";
if(boost::is_base_of<Blank, CombinedType::BComponent>::value)
std::cout << "composed of B \n";
if(boost::is_base_of<Blank, CombinedType::CComponent>::value)
std::cout << "composed of C \n";
}
int main()
{
typedef A<B<C<Blank>>> ComposedType;
ComposedType ct;
printTypeComponents(ct);
//typedef A<C<Blank>> ComposedType2;
//ComposedType2 ct2;
//printTypeComponents(ct2);
}
I am using MSVC2010
Thank you!
EDIT:
I am not actually interested in names of types... I want to use it like:
if(composedOfA)
doSomeCharacteristicStuffFromA(); //member function of A
if(composedOfB)
doSomeCharacteristicStuffFromB(); //member function of B

My attempt (without using C++0x feature(s))
//----------------------------------------
struct null{};
template<typename>
struct split
{
typedef null Ct;
typedef null At;
};
template<template<typename> class C, typename T>
struct split<C<T> >
{
typedef C<null> Ct; //class template
typedef T At; //argument type
};
template<template<typename> class C>
struct split<C<Blank> >
{
typedef C<null> Ct; //class template
typedef Blank At; //argument type
};
template<typename T, typename U>
struct is_same
{
static const bool value = false;
};
template<typename T>
struct is_same<T,T>
{
static const bool value = true;
};
typedef A<null> anull;
typedef B<null> bnull;
typedef C<null> cnull;
//----------------------------------------
template <typename CombinedType>
void printTypeComponents(const CombinedType & t)
{
typedef typename split<CombinedType>::Ct Ct;
typedef typename split<CombinedType>::At At;
if ( is_same<Ct,anull>::value )
cout << "A" << endl;
else if ( is_same<Ct,bnull>::value )
cout << "B" << endl;
else if ( is_same<Ct,cnull>::value )
cout << "C" << endl;
if ( !is_same<At,Blank>::value )
printTypeComponents(At());
else
cout << "Blank" << endl;
}
Test code:
int main()
{
typedef A<B<C<Blank> > > ComposedType;
ComposedType ct;
printTypeComponents(ct);
cout<<"-------"<<endl;
typedef A<C<Blank> > ComposedType2;
ComposedType2 ct2;
printTypeComponents(ct2);
}
Output:
A
B
C
Blank
-------
A
C
Blank
Online Demo : http://ideone.com/T5nD4

Exploiting your structure, what about:
template <template <typename> class X, typename T>
void print_type(const X<T>& x, char (*)[std::is_base_of<T, X<T>>::value] = 0)
{
std::cout << "Base: " << typeid(T).name() << "\n";
print_type<T>(x);
}
template <typename T>
void print_type(const T&) {}

Here is a template unraveller that uses variadic typenames. You can probably make it work in VS2010 with the usual macro tricks (e.g. like in the pretty-printer.)
template <typename T> class A : public T {};
template <typename T> class B : public T {};
template <typename T> class C : public T {};
struct NullType {};
#include <tuple>
#include <iostream>
template <typename ...Args> struct Concat;
template <typename T, typename ...Args>
struct Concat<T, std::tuple<Args...>>
{
typedef std::tuple<T, Args...> type;
};
template <typename> struct Unravel;
template <typename T, template <typename> class X>
struct Unravel<X<T>>
{
typedef typename Concat<X<T>, typename Unravel<T>::type>::type type;
};
template <template <typename> class X>
struct Unravel<X<NullType>>
{
typedef std::tuple<X<NullType>> type;
};
template <typename T> struct printArgs;
template <typename T, typename ...Args>
struct printArgs<std::tuple<T, Args...>>
{
static void print() { std::cout << "Have type." << std::endl; printArgs<std::tuple<Args...>>::print(); }
};
template <typename T>
struct printArgs<std::tuple<T>>
{
static void print() { std::cout << "Have type." << std::endl; }
};
int main()
{
typedef A<B<C<NullType>>> CType;
printArgs<Unravel<CType>::type>::print();
}
It won't print anything exciting, so at the moment you just get one line per inheritance, but if you partially-specialize printArgs you can print specific information for your types.

This might work for you (if I understood the question correctly). I got it working with gcc, but think it should work even in VS2010.
void printTypeComponents(const Blank&)
{
std::cout << "composed of Blank\n";
}
template <typename T>
void printTypeComponents(const A<T>&)
{
std::cout << "composed of A\n";
printTypeComponents(T());
}
template <typename T>
void printTypeComponents(const B<T>&)
{
std::cout << "composed of B\n";
printTypeComponents(T());
}
template <typename T>
void printTypeComponents(const C<T>&)
{
std::cout << "composed of C\n";
printTypeComponents(T());
}
The advantage is that you do not need any typedefs inside the classes. If you want, you can put the logic inside printTypeComponentsImpl (or something like that) and have printTypeComponents delegate to that function.
You can avoid creating the temporaries, but since you cannot partially specialize functions, you'll have to move everything inside a struct and use that. If you want, I can put code example here.
edit: You could actually automate it a little bit with typeid(x).name(), provided you can extract the name of class template from it (named getTemplateName here).
template <template <typename> class T, typename U>
void printTypeComponents(const T<U>&)
{
std::cout
<< "composed of "
<< getTemplateName(typeid(T<DummyClass>).name())
<< '\n';
printTypeComponents(U());
}
For those interested, here's gcc specific example.

Related

How to tell if template type is an instance of a non-variadic template class?

This question is awful similar to How to tell if template type is an instance of a template class?
I would like to detect if a template parameter is from one particular template class that has no variadic template arguments.
template<class U, class S>
struct A{};
template<class T>
struct B {
B() {
if constexpr (T == A) {
// T is a template instantiation of `A`.
} else {
}
}
};
I can't change A's definition. I can change B's definition to have additional template parameters.
How do I implement (T == A) given the restriction of not knowing A's U and S?
I would go for a partial specialization here.
#include <iostream>
template<class U, class S>
struct A{};
template<class T>
struct B {
B() {
std::cout << "None-A implementation\n";
}
};
template<class U, class S>
struct B<A<U, S>> {
B() {
std::cout << "A implementation\n";
}
};
int main() {
B<int> b1;
B<A<int, int>> b2;
}
You have the option of leaving the default-case without an implementation.
Or you can have a fallback implementation for any none-A classes like here.
If the partial specialization forces too much code duplication you can also extract the detection part to it's own template variable like this.
#include <iostream>
template<class U, class S>
struct A{};
template <class T>
constexpr bool is_A_instatiation = false;
template <class U, class S>
constexpr bool is_A_instatiation<A<U, S>> = true;
template<class T>
struct B {
B() {
if constexpr (is_A_instatiation<T>) {
std::cout << "A instatiation!\n";
} else {
std::cout << "none-A instatiation!\n";
}
}
};
int main() {
B<int> b1;
B<A<int, int>> b2;
}
The easiest way is:
template<class T>
struct B{/*default implementation*/};
template<class U,class S>
struct B<A<U,S>>{/*Specified implementation*/};
A<T,U>: you already know it and search key
B<...>: variadic types which may include A<T,U> - known type
And you want to search A<T,U> in B<...>
template <typename T, typename U>
struct A {};
template <typename T, typename U, typename ...Ts>
struct B {
static constexpr bool value = ((std::is_same_v< A<T, U>, Ts> || ... ));
};
int main() {
std::cout << std::boolalpha <<
B<int,float, int, int, float, A<int,float>>::value << '\n'<<
B<int,float, int, int, float>::value <<std::endl;
}

Template : class specialization

I'm new in the C++ world.
Sorry for my nooby question.
I have a class
template <typename T>
class Foo
{
T t_;
void say_hello()
{ std::cout << "Ciao";}
// work with T ...
};
I want to specialize this template class for 3 types.
If type is (A or B or C), Then use this class
template<>
class Foo<A or B or C>
{
void say_hello()
{ std::cout << "Hello";}
};
What's the best way to do this?
Thank you for your help.
A possible solution uses SFINAE
template <typename T, typename = void>
class Foo
{
T t_;
void say_hello()
{ std::cout << "Ciao";}
// work with T ...
};
template <typename T>
class Foo<T, std::enable_if_t<std::is_same_v<T, A>,
|| std::is_same_v<T, B>,
|| std::is_same_v<T, C>>
{
void say_hello()
{ std::cout << "Hello";}
};
If you don't use T inside the Foo specialization (as in your example) you can also use a sort of self-inheritance
template <typename T>
class Foo
{
T t_;
void say_hello()
{ std::cout << "Ciao";}
// work with T ...
};
template <>
class Foo<A>
{
void say_hello()
{ std::cout << "Hello";}
};
template <>
class Foo<B> : public Foo<A>
{ };
template <>
class Foo<C> : public Foo<A>
{ };
Off Topic: if you want to use say_hello() outside the class, is better if you make it public (or if you declare Foo as a struct).
There are several possibilities, for example:
Specialization of the method only:
template<>
void Foo<A>::say_hello() { std::cout << "Hello"; }
template<>
void Foo<B>::say_hello() { std::cout << "Hello"; }
template<>
void Foo<C>::say_hello() { std::cout << "Hello"; }
or, in C++17, you might do:
template <typename T>
class Foo
{
T t_;
void say_hello()
{
if constexpr(std::is_same_v<T, A> || std::is_same_v<T, B> || std::is_same_v<T, C>) {
std::cout << "Hello";
} else {
std::cout << "Ciao";
}
}
// work with T ...
};
Whereas regular if works in that example, it would fail if you call code specific to A, B, C.
if constexpr won't have that issue.
A variant of the SFINAE solution that is a bit more concise for more classes.
template<class T, class... Ts>
struct is_one_of;
template<class T, class Ts>
struct is_one_of<T, T, Ts...> : std::true_type {}; //maybe add std::decay_t
template<class T, class S, class Ts>
struct is_one_of<T, S, Ts...> : is_one_of<T, Ts...> {};
template<class T>
struct is_one_of<T> : std::false_type{};
template<class T, class... Ts>
constexpr bool is_one_of_v = is_one_of<T, Ts...>::value;
template <typename T, typename = void>
class Foo
{
T t_;
void say_hello()
{ std::cout << "Ciao";}
// work with T ...
};
template <typename T>
class Foo<T, std::enable_if_t<is_one_of_v<T, A, B, C>
{
void say_hello()
{ std::cout << "Hello";}
};

Better pattern for partial specialization disambiguation precedence chain?

Consider the following series of partial specializations:
template <typename T, typename Enable=void>
struct foo {
void operator()() const { cout << "unspecialized" << endl; }
};
template <typename T>
struct foo<T, enable_if_t<
is_integral<T>::value
>>{
void operator()() const { cout << "is_integral" << endl; }
};
template <typename T>
struct foo<T, enable_if_t<
sizeof(T) == 4
and not is_integral<T>::value
>>{
void operator()() const { cout << "size 4" << endl; }
};
template <typename T>
struct foo<T, enable_if_t<
is_fundamental<T>::value
and not (sizeof(T) == 4)
and not is_integral<T>::value
>>{
void operator()() const { cout << "fundamental" << endl; }
};
// etc...
Live Demo
I see this kind of thing all of the time (indeed, another StackOverflow answer elsewhere gives the same pattern for a similar problem). While this works, this code has some serious maintainability issues, and also precludes, e.g., user-level partial specializations at higher priority if the above code is in a library. What's a better pattern for expressing this idea? I feel like there has to be something (maybe involving inheritance and variadic template parameters?) that can express this idea more cleanly and maintainably. (Suppose also that each of the specializations is a full-on class rather than a simple functor, so overloaded functions don't work in a simplistic way).
The overgrowth of condition count can be solved by helper structs:
#include <iostream>
#include <type_traits>
using namespace std;
template <bool ThisCondition, class ParentCondition = void, class = void>
struct condition_resolver {
static constexpr bool is_condition_resolver = true;
static constexpr bool parent_condition_v = !ThisCondition;
static constexpr bool value = ThisCondition;
};
template <bool ThisCondition, class ParentCondition>
struct condition_resolver<ThisCondition, ParentCondition, enable_if_t<ParentCondition::is_condition_resolver> > {
static constexpr bool is_condition_resolver = true;
static constexpr bool parent_condition_v = !ThisCondition && ParentCondition::parent_condition_v;
static constexpr bool value = ThisCondition && ParentCondition::parent_condition_v;
};
template <typename T, typename Enable=void>
struct foo {
void operator()() const { cout << "unspecialized" << endl; }
};
template <typename T>
struct is_integral_foo: condition_resolver<is_integral<T>::value> { };
template <typename T>
struct foo<T, enable_if_t<is_integral_foo<T>::value>>{
void operator()() const { cout << "is_integral" << endl; }
};
template <typename T>
struct has_size_four_foo: condition_resolver<sizeof(T) == 4, is_integral_foo<T>> { };
template <typename T>
struct foo<T, enable_if_t< has_size_four_foo<T>::value>>{
void operator()() const { cout << "size 4" << endl; }
};
template <typename T>
struct is_fundamental_foo: condition_resolver<is_fundamental<T>::value, has_size_four_foo<T>> { };
template <typename T>
struct foo<T, enable_if_t<is_fundamental_foo<T>::value>>{
void operator()() const { cout << "fundamental" << endl; }
};
typedef char four_sized[4];
int main() {
foo<int>()();
foo<four_sized>()();
foo<nullptr_t>()();
}
Output:
is_integral
size 4
fundamental
PS.
Have in mind that void which is also fundamental will cause compiler to produce a warning that sizeof(void) is considered...
Edit:
If you really need to use specialization for solving the overgrowth of condition problem this might interest you:
#include <iostream>
#include <type_traits>
using namespace std;
template <class Tag, int Level, class... Args>
struct concrete_condition_resolver;
template <class Tag, int Level, class... Args>
struct condition_resolver;
template <class ConditionResolver>
struct condition_resolver_parent {
template<class CR = ConditionResolver>
constexpr enable_if_t<CR::level != 0, bool> operator()(bool parent) {
return (!parent && static_cast<const ConditionResolver*>(this)->condition && typename ConditionResolver::LevelUp()(true)) ||
(parent && !static_cast<const ConditionResolver*>(this)->condition && typename ConditionResolver::LevelUp()(true));
}
template<class CR = ConditionResolver>
constexpr enable_if_t<CR::level == 0, bool> operator()(bool parent) {
return (!parent && static_cast<const ConditionResolver*>(this)->condition) ||
(parent && !static_cast<const ConditionResolver*>(this)->condition);
}
};
template <class Tag, int Level, class... Args>
struct condition_resolver: concrete_condition_resolver<Tag, Level, Args...>, condition_resolver_parent<condition_resolver<Tag, Level, Args...>> {
using LevelUp = condition_resolver<Tag, Level - 1, Args...>;
using tag = Tag;
static constexpr int level = Level;
constexpr condition_resolver() {}
};
struct foo_tag { };
template <class First, class... Args>
struct concrete_condition_resolver<foo_tag, 0, First, Args...> {
static constexpr bool condition = is_integral<First>::value;
};
template <class First, class... Args>
struct concrete_condition_resolver<foo_tag, 1, First, Args...> {
static constexpr bool condition = sizeof(First) == 4;
};
template <class First, class... Args>
struct concrete_condition_resolver<foo_tag, 2, First, Args...> {
static constexpr bool condition = is_fundamental<First>::value;
};
template <typename T, typename = void>
struct foo;
template <typename T>
struct foo<T, enable_if_t<condition_resolver<foo_tag, 0, T>()(false)>>{
void operator()() const { cout << "is_integral" << endl; }
};
template <typename T>
struct foo<T, enable_if_t<condition_resolver<foo_tag, 1, T>()(false)>>{
void operator()() const { cout << "size 4" << endl; }
};
template <typename T>
struct foo<T, enable_if_t<condition_resolver<foo_tag, 2, T>()(false)>>{
void operator()() const { cout << "is_fundamental" << endl; }
};
typedef char four_sized[4];
int main() {
foo<int>()();
foo<four_sized>()();
foo<nullptr_t>()();
}
This approach is applicable even for overload functions using enable_if, while partial specialization deals only with structs...
Why am I answering my own question
So I've been bugged by this ever since asking this question, and I was never completely satisfied with the original answer. After much fiddling and trial/error, I've come up with a pattern I'm much happier with that uses tag dispatch. Whether or not it's actually better, more readable, and more maintainable than the previous answer is for you to judge, but I like it better. Feel free to pick it apart, criticize it, and break it. :-)
The Basic Version
Without further ado, here's the code that solve the simplest version of the problem
template <typename> struct always_true : true_type { };
template <typename> struct always_false : false_type { };
template <typename T, template <class...> class condition=always_false,
typename flag=integral_constant<bool, condition<T>::value>
>
struct foo;
////////////////////////////////////////
// "unspecialized" version
// put always_true and false_type together here so that no one gets here accidentally
template <typename T, typename true_or_false_type>
struct foo<T, always_true, true_or_false_type> {
void operator()() const { cout << "unspecialized" << endl; }
};
////////////////////////////////////////
// is_fundamental
template <typename T>
struct foo<T, is_fundamental, true_type> {
void operator()() const { cout << "is_fundamental" << endl; }
};
template <typename T> struct foo<T, is_fundamental, false_type> : foo<T, always_true> { };
////////////////////////////////////////
// is_integral
template <typename T>
struct foo<T, is_integral, true_type> {
void operator()() const { cout << "is_integral" << endl; }
};
template <typename T>
struct foo<T, is_integral, false_type> : foo<T, is_fundamental> { };
////////////////////////////////////////
// sizeof(T) == 4
template <typename T>
using size_is_4 = integral_constant<bool, sizeof(T) == 4>;
template <typename T>
struct foo<T, size_is_4, true_type> {
void operator()() const { cout << "size_is_4" << endl; }
};
template <typename T>
struct foo<T, size_is_4, false_type> : foo<T, is_integral> { };
////////////////////////////////////////
// Now put the most specialized condition in the base of this template
template <typename T, typename true_or_false_type>
struct foo<T, always_false, true_or_false_type> : foo<T, size_is_4> { };
The chain of precedence, held in a helper struct in the previous answer, is encoded in inheritance.
More bells and whistles
Adding the ability to enable user partial specializations with higher precedence than the library ones takes a little more doing, but the principle is the same. The full version in this demo.

Template method specialization for multiple types

I have a class “A” which exposes the template method foo.
Foo has a standard implementation which works fine with B,C. It also has a special implementation for D.
class A
{
template<typename T>
void foo()
{
//standard implementation
}
template<>
void foo<D>
{
//special implementation
}
}
class B{};
class C{};
class D{};
int main()
{
A<B> a1;
A<C> a2;
A<D> a3;
}
Now, I need to add the class E, which requires for "foo" the same special implementation as D.
Is there a way to say something like: For all the types use the standard foo. For D,E (and so on) the special implementation.
class A
{
template<typename T>
void foo()
{
//standard implementation
}
template<>
void foo<D && E> <-- PseudoCode - It doesn't work
{
//special implementation
}
}
class B{};
class C{};
class D{};
class E{};
int main()
{
A<B> a1;
A<C> a2;
A<D> a3;
A<E> a4;
}
I was thinking to use the trait classes. But I was hoping there is something simpler to achieve this.
Thanks
Using Walter Brown's (C++1z) void_t.
#include <iostream>
#include <type_traits>
template <typename...>
using void_t = void;
template <typename T, typename = void>
struct has_bar
: std::false_type { };
template <typename T>
struct has_bar<T, void_t<decltype( std::declval<T&>().bar() ) > >
: std::true_type { };
class A {
public:
void foo() { };
};
class B {
public:
void bar() { };
};
class C {
public:
void bar() { };
};
template <typename T>
typename std::enable_if<!has_bar<T>::value, void>::type
fun(T t) {
std::cout << "fun" << std::endl;
}
template <typename T>
typename std::enable_if<has_bar<T>::value, void>::type
fun(T t) {
std::cout << "special fun" << std::endl;
}
The code...
int main(const int argc, const char* argv[argc]) {
A a;
B b;
C c;
fun(a);
fun(b);
fun(c);
return 0;
}
prints out
fun
special fun
special fun
Note, that does not check any type semantics, so it may be better declaring bar() as an interface and using std::is_base_of.
You should take a look on SFINAE to enable and disable function at compile time
If D and E are special, they have let's say the member void bar() and not the others, you can actually implement your own type trait:
template<typename T>
struct has_bar {
private:
template<typename C> static std::true_type test(decltype(&C::bar)*);
template<typename C> static std::false_type test(...);
public:
constexpr static bool value = decltype(test<T>(nullptr))::value;
};
/* false */ /* true */
cout << boolalpha << has_bar<A> << " " << has_bar<E> << endl;
Now with this type trait you can use std::enable_if as a compile time switch:
/* standard if no bar */
template<typename T, typename = enable_if_t< !has_bar<T> >>
void foo()
{
//standard implementation
}
/* special if bar */
template<<typename T, typename = enable_if_t< has_bar<T> >>
void foo()
{
//special implementation
}
AFAIK there's no way you can do this without defining some SFINAE machinery. Now the minimum I can think of without including type_traits header would be the following:
Define "home made "enable_if and is_same type traits as follows.
namespace mine {
template<bool, typename T = void> struct enable_if {};
template<typename T> struct enable_if<true, T> { typedef T type; };
template<typename T, typename U> struct is_same { static bool const value = false; };
template<typename T> struct is_same<T, T> { static bool const value = true; };
};
Apply SFINAE in member function foo() of class A as follows:
class A {
template<typename T>
struct pred {
static bool const value = mine::is_same<T, B>::value ||
mine::is_same<T, C>::value || mine::is_same<T, D>::value || mine::is_same<T, E>::value;
};
public:
template<typename T>
typename mine::enable_if< pred<T>::value, void>::type
foo() { std::cout << "special implementation" << std::endl; }
template<typename T>
typename mine::enable_if<!pred<T>::value, void>::type
foo() {std::cout << "standard implementation" << std::endl; }
};
LIVE DEMO
P.S the bonus is that the above solution works also for pre C++11 compilers.

Is it possible to selectively define a type in a derived class

I have a class template which looks like this:
template <Base>
struct foo : Base
{
typedef int some_type;
};
and I have a base which looks like this:
struct some_base
{
typedef float some_type;
};
Now foo<some_base>::some_type will be int as the derived foo will hide the Base::some_type. What I would like to do, is that if Base::some_type is defined, use that else, define some_type locally in foo as 'int - so question is, is this possible?
I could invert the relationship and save myself some headache, however it's not very logical in the real application...
Anything is possible with a bit of template metaprogramming :)
Start by writing a metafunction that determines whether a type has a nested type called "some_type". Something like this:
template <typename T>
struct has_some_type
{
typedef char no; // type with sizeof == 1
typedef struct { char x[2]; } yes; // type with sizeof == 2
template <typename X, typename Y = typename X::some_type>
struct foo {};
template <typename X>
static yes test(foo<X>*);
template <typename X>
static no test(...);
static const bool value = (sizeof(test<T>(0)) == sizeof(yes));
};
Now you can do something like this in the derived class:
template <typename T, bool has_some_type>
struct get_some_type;
template <typename T>
struct get_some_type<T, true>
{
typedef typename T::some_type type;
};
template <typename T>
struct get_some_type<T, false>
{
typedef int type; // the default type
};
template <typename base>
class derived : base
{
typedef typename get_some_type<base, has_some_type<base>::value>::type some_type;
...
};
This should work:
struct sfinae_types
{
struct yes { char x; };
struct no { char x[2]; };
};
template<class T>
class has_some_type : sfinae_types
{
private:
template<class U>
static yes test(typename U::some_type *);
template<class U>
static no test(...);
public:
enum { value = (sizeof(yes) == sizeof(test<T>(0))) };
};
template<bool, class T, typename DT>
struct get_some_type
{
typedef DT type;
};
template<class T, typename DT>
struct get_some_type<true, T, DT>
{
typedef typename T::some_type type;
};
struct B1
{
};
struct B2
{
typedef float some_type;
};
template<typename T>
struct D : T
{
typedef typename get_some_type<has_some_type<T>::value, T, int>::type some_type;
};
#include<iostream>
#include<typeinfo>
int main()
{
std::cout << has_some_type<B1>::value << std::endl;
std::cout << typeid(D<B1>::some_type).name() << std::endl;
std::cout << has_some_type<B2>::value << std::endl;
std::cout << typeid(D<B2>::some_type).name() << std::endl;
return(0);
}
And is a slight variation of what HighCommander4 presented a few seconds above...
I guess boost::mpl may come handy here and provide some useful TMP expressions I hand crafted above.
Give struct foo an additional template argument that defaults to int:
template <Base, Typedef = int>
struct foo : Base
{
typedef Typedef some_type;
};
Then foo<some_base, some_base::some_type>::some_type is some_base::some_type.