2

I have a .h file with all my templates in it and a .cpp file with my main.

Part of .h templates:

   template<int N, int P>
    struct BOUND {
        static inline int eval(int v) {
            //...
            return 1; 
        };
    };

    template<class K>
    struct VAL_x {
        static inline int eval(int v) {
            //...
            return 1;
        };
    };

    template<int L, class K>
    struct LIT {
        static inline int eval(int v) {
            //...
            return 1;
        };
    };

    template<class A, class B, class K>
    struct ADD {
        static inline int comp_b(int v){
            // HERE check if class A is LIT  or VAL_x
            //...
            return 2;
        };
    };

Here is how I call in my main() this template:

int main() {

    typedef ADD<VAL_x<BOUND<2,3> >, LIT<2, BOUND<2,3> >, BOUND<2,3> > FORM;
    FORM exec_form;

    int y = 2;

    int bounds = exec_form.comp_b(y);

    return 0;
}

How can I know in ADD::comp() function of my struct, if an argument that was passed is instance of a specific class (e.g. LIT<> )? Those arguments can be passed in any order (e.g all arguments could be LIT, or only the second one)

NOTE: there are also other structs apart from VAL_x , LIT, BOUND and ADD.

Marialena
  • 817
  • 8
  • 31
  • You mean an argument in a template right? Not the argument of `comp()`. A minimal example would be nice here. :) – gsamaras May 02 '16 at 18:53
  • Your example won't work since you're missing the template arguments of `something` – Daniel May 02 '16 at 18:56
  • @Dani I am sorry it is because I tried to change the names and forgot about it... I will update it now to be more understandable. – Marialena May 02 '16 at 18:57
  • @gsamaras @ Dani I have updated my code. – Marialena May 02 '16 at 19:04
  • Thank you @marialena, what's the purpose of this `template`? – gsamaras May 02 '16 at 19:06
  • I haven't added there body.. `LIT` is going to use `L` parameter to do some computations. But I don't need that value.. I only need to know if in` ADD` struct one of the template parameters input is instance of the struct `LIT`, or `Val_x`. – Marialena May 02 '16 at 19:09

2 Answers2

4

Option #1

Introduce a separate trait for each class template of interest (C++03 doesn't help here much).

template <bool B> struct bool_constant { static const bool value = B; };
template <bool B> const bool bool_constant<B>::value;

template <typename T>   struct is_LIT : bool_constant<false> {};
template <int L, int M> struct is_LIT<LIT<L, M> > : bool_constant<true> {};

template <typename T> struct is_VAL_x : bool_constant<false> {};
template <int K>      struct is_VAL_x<VAL_x<K> > : bool_constant<true> {};

template <class A, class B>
struct ADD 
{
    static inline int comp_b(int v)
    {
        if (is_LIT<A>::value && is_VAL_x<B>::value)
        {

        }

        return 2;
    }
};

DEMO

Option #2

Use a generic custom trait, whose specialization detects if the type passed is an instantiation of the specified template-template parameter (it is if the specialization matches, i.e., T is an instantiation of class template X):

template <template <int> class X, typename T>
struct is_template { static const bool value = false; };

template <template <int> class X, int N>
struct is_template<X, X<N> > { static const bool value = true; };

template <typename A, typename B>
struct ADD 
{
    static inline int comp_b(int v)
    {
        if (is_template<VAL_x, A>::value && is_template<LIT, B>::value)
        {
        }

        return 2;
    }
};

DEMO 2

Option #3

Use tag-dispatching, possibly add overloads for other class templates that return true/false, making it similar to Option #1. This solution also relies on overload resolution, that prefers more specialized function templates over those less constrained/generic.

template <typename T> struct tag {};

template <typename A, typename B>
struct ADD 
{
    static inline int comp_b(int v)
    {
        return comp_b(v, tag<A>(), tag<B>());
    }

    template <int M, int N>
    static inline int comp_b(int v, tag<LIT<M> >, tag<VAL_x<N> >)
    {
        return 1;
    }

    template <typename T, typename U>
    static inline int comp_b(int v, tag<T>, tag<U>)
    {
        return 2;
    }
};

DEMO 3

Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
  • 1
    Piotr, that's brilliant!! I do not know if you upvote my answer, but this is better and it deserves more upvotes from mine! Could you please explain a bit your solution? At least one. :) – gsamaras May 02 '16 at 19:33
  • 1
    I have tried to follow the first option. As I can see your example is affected from the number of template parameters of the structs. So I have put the correct number of parameters that my struct take. I haven't thought that It would matter. If you could just explain to me how your example works, I could change it so that it can fit my case. What is changed is that `ADD` takes three parameters and `LIT` takes 2. But in the `ADD` struct I only want to check the classes of the first and second template parameter. I don't care about the third one. – Marialena May 02 '16 at 19:46
  • @marialena I think what you are trying to achieve is a templated AST, am I right? If I am right you do not need to "branch" on template arguments types, they already provide the point for changing implementation, at most you have to pass around a "Environment" parameter to set values for variables. – CoffeDeveloper May 02 '16 at 20:01
  • @DarioOO without be 100% percent sure, I think yes... I am new to C++ templates so I am just trying to learn how templates work and how they interact with each other. – Marialena May 02 '16 at 20:05
  • Ah.. you do not have a "specific goal" rather than learning, you have to told that next time :). You could look there: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Expression-template I think Piotr answer is quite advanced for a learner (I have to read it very slow to understand what it does, however writing templates is much easier then reading them XD ahem) – CoffeDeveloper May 02 '16 at 20:07
  • 1
    @DarioOO no no you misunderstood me.. It is a small part of a coursework. I just simplified the details in the code. I just wanted to know if I can identify the class of a parameter.. But of course the solutions needed a complete example in order to be applied in my case. I am sorry for any inconvenience caused. I will try to see the updated options of Piotr. Thank you both. – Marialena May 02 '16 at 20:14
  • @Piotr Skotnicki, it is difficult to apply the above solutions to the updated parameters in the above templates : `template struct BOUND { ... }` , `template struct VAL_x { ... }`, `template struct LIT { ... }` and `template struct ADD { ... }` and the way we call it through main: `ADD >, LIT<2, BOUND<2,3> >, BOUND<2,3> >`. Thanks a lot for your time. I will try to make it work through your guidance. – Marialena May 02 '16 at 21:38
2

You could do it like this:

#include <typeinfo>
...
template<class A, class B>
struct ADD {

    static inline int comp_b(int v){
        // HERE check if class A is LIT  or VAL_x
        std::cout << ( typeid(A)==typeid(VAL_x) ) << '\n';
        return 2;
    };
};

where I am using std::type_info, which will print 1, for true evaluation.

Or, with , you could do:

#include <type_traits>
...
if (std::is_same<A, VAL_x>::value)
    std::cout << "they are same!\n";

However, you could overload a function or such. Make sure you read this: How do I check my template class is of a specific classtype? and this How to check for the type of a template parameter?

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • I have updated my code; my `VAL_x` struct is also within a template like `LIT`. I am trying to add in `ADD` struct the first solution you suggest but `VAL_x` needs template arguments. In case of `VAL_x` i know the argument. But in the case of `LIT` i don't know it. This is what I tried but has an error for missing template arguments. `bool isLIT = typeid(A)==typeid(VAL_x); isLIT ? "true" : "false"; printf("%s \n", isLIT);` – Marialena May 02 '16 at 19:22
  • @marialena that makes sense, doesn't it? :) This checking is made in compile time, thus you should provide the argument as well. For example VAL_x<5> will work, but you are saying is that it might be 4 tomorrow, right (which are not the same)? – gsamaras May 02 '16 at 19:26
  • Yes.. It makes sense of course. The formula that I give in main can be anything. For example `LIT` could be the first parameter and `VAL_x` could be the last. Or both could be `LIT` or `VAL_x`. I just want to check their classes in `ADD`. – Marialena May 02 '16 at 19:28
  • @marialena, Piotr's answer also makes sense, check it out!! Thanks for the upvote. – gsamaras May 02 '16 at 19:30