1

In summary, I would like to be able to check if the type of an object matches some type or if two objects match types.

The essence of what I'm trying to do is pasted below:

    #include <vector>
    #include <iostream>
    #include <type_traits>

    template< class T1, class T2 >
    bool compare_types(T1, T2)
    {
        return std::is_same<T1, T2>::value;   
    }

    class OBJ
    {
        
    };

    int main(int argc, char *argv[])
    {               

        OBJ a;
        OBJ b;
        int c;
        
        
        std::cout<<"\n"<<compare_types(a, b)<<"\n"; // ok and returns true
        //std::cout<<"\n"<<compare_types(c, int)<<"\n"; // compile error, ideally return true
        //std::cout<<"\n"<<std::is_same<c, int>::value<<"\n"; // compile error, ideally return trues
        //std::cout<<"\n"<<compare_types(a, OBJ)<<"\n"; // compile error, ideally return true
        //std::cout<<"\n"<<std::is_same<a, OBJ>::value<<"\n"; // compile error, ideally return true
        //std::cout<<"\n"<<compare_types(a, std::vector)<<"\n"; // compile error, ideally return false
        //std::cout<<"\n"<<std::is_same<a, b>::value<<"\n"; // compile error, ideally return true
        //std::cout<<"\n"<<std::is_same<a, c>::value<<"\n"; // compile error, ideally return false
        //std::cout<<"\n"<<std::is_same<int, float>::value<<"\n"; // compile error, ideally return false
        std::cout<<"\n"<<std::is_same<int, std::int32_t>::value<<"\n"; // ok and returns true
        
        return 0;        
    }
cigien
  • 57,834
  • 11
  • 73
  • 112
Tony A
  • 98
  • 1
  • 6
  • Are you actually constrained to C++11, or can you use later language revisions as well? – cigien Jan 03 '22 at 18:02
  • 2
    You've misunderstood it somehow. You can't supply `int` as an argument to a function. Either supply it as a template parameter or supply an instance of `int`, like `std::cout<<"\n"< – Ted Lyngmo Jan 03 '22 at 18:05
  • That is a good question. I'm doing some work on a framework that is currently compiled as gnu++11. I would be very hesitant to pull the entire framework forward, at the risk of breaking other things. In summary, yes I'm bound to C++11. That is unless you could say that pulling everything forward would be backwards compatible with what exists. – Tony A Jan 03 '22 at 18:05
  • 1
    ? You know _statically_ when writing code if something is a variable or not. I would just provide a `compare_type(a)` interface with one template argument. I would just do `std::is_same::value` anyway... I do not see, why do you need the function at all? – KamilCuk Jan 03 '22 at 18:08
  • @KamilCuk thank you, I was making things more complicated than needed. – Tony A Jan 03 '22 at 18:28
  • 1
    Yes, your code base should compile just fine with a later language revision. C++ is mostly backwards compatible, and if something breaks, there's a decent chance it was an unnoticed bug in the first place. Simply try compiling with the latest version you have access to, and see what happens. – cigien Jan 03 '22 at 18:32
  • @cigien I will certainly give it a spin to see what happens. As I've been modernizing parts of this framework, I've definitely ran into instances where compiling at 14' or 17' would make everything much simpler. – Tony A Jan 03 '22 at 18:35
  • @TonyA You don't need to make the changes directly in your code. If you haven't used the online compilers yet, give one of those a try. It's easy to test things out quickly using those. I added a Demo link to my answer where you can play around. – Ted Lyngmo Jan 03 '22 at 18:54
  • @cigien None of the commented out code will compile in C++20 or earlier revisions... but, you are not suggesting that it should, are you? – Ted Lyngmo Jan 03 '22 at 19:04
  • @TedLyngmo No, not at all :) It's just that the OP had tagged this with C++11 (and that's still mentioned in the title), so I was just wondering if that's an actual constraint for the OP, or not. – cigien Jan 03 '22 at 19:06
  • @cigien Phew... :-) – Ted Lyngmo Jan 03 '22 at 19:06

1 Answers1

2
  • Function arguments should be instances. int is not an instance. It's a type.
  • Template parameters can be types (and non-types).

So, you need to pass an instance of int to your compare_types:

    std::cout << compare_types(c, int{}) << '\n';

And a type when you use c as a template parameter. Fortunately, decltype(c) provides the type:

    std::cout << std::is_same<decltype(c), int>::value << '\n';

Continue this pattern and your program would look like:

#include <iostream>
#include <type_traits>
#include <vector>

template<class T1, class T2>
bool compare_types(T1, T2) {
    return std::is_same<T1, T2>::value;
}

class OBJ {};

int main(int argc, char* argv[]) {
    OBJ a;
    OBJ b;
    int c;

    std::cout << compare_types(a, b) << '\n'
              << compare_types(c, int{}) << '\n'
              << std::is_same<decltype(c), int>::value << '\n'
              << compare_types(a, OBJ{}) << '\n'
              << std::is_same<decltype(a), OBJ>::value << '\n'
              << std::is_same<decltype(a), decltype(b)>::value << '\n'
              << std::is_same<decltype(a), decltype(c)>::value << '\n'
              << std::is_same<int, float>::value << '\n'
              << std::is_same<int, std::int32_t>::value << '\n';

    // std::cout << compare_types(a, std::vector) << '\n';
}

Demo

I don't know what you hope for with std::vector there. It's not a type in itself. It's a template, so it'd need at least one template parameter (or in C++17 and later versions, something that makes it possible to deduce T).

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108