Search code examples
templatesc++11stlstdtupletype-deduction

Understanding type deduction through std::is_same


I want to have a std::tuple of a specific size and also provide a function that takes as many arguments as the tuple and of the same exact types.

I thought I could use a variadic template function to construct a tuple from the parameter pack and compare the two tuples with std::is_same

Here is some sample code to further explain what I' ve tried

#include <tuple>
#include <iostream>
#include <string>
#include <typeinfo>

static const auto TupleInts =
     std::make_tuple(
        1,
        2,
        3
    );

static const auto TuplePairs =
    std::make_tuple(
        std::make_pair(1, 1),
        std::make_pair(2, 2),
        std::make_pair(3, 3)
    );

typedef decltype(TupleInts) TupleIntsType;
typedef decltype(TuplePairs) TuplePairsType;
typedef std::tuple<int, int, int> TupleType;

template<typename... Ts>
bool compare(Ts... vals) {
    std::cout << typeid(std::tuple<Ts...>).name() << std::endl;
    std::cout << typeid(TupleType).name() << std::endl;

    return std::is_same < std::tuple<Ts...>, TupleType >::value;
}

template<typename... Ts>
bool comparePairsTuple(Ts... vals) {
    std::cout << typeid(std::tuple<std::pair<int, Ts>...>).name() << std::endl;
    std::cout << typeid(TuplePairsType).name() << std::endl;

    return std::is_same < std::tuple<std::pair<int, Ts>...>, TuplePairsType >::value;
}

template<typename... Ts>
bool compareIntsTuple(Ts... vals) {
        std::cout << typeid(std::tuple<Ts...>).name() << std::endl;
    std::cout << typeid(TupleIntsType).name() << std::endl;

    return std::is_same < std::tuple<Ts...>, TupleIntsType >::value;
}

int main() {
    std::cout << comparePairsTuple(1, 2, 3) << std::endl;
    std::cout << compareIntsTuple(1, 2, 3) << std::endl;
    std::cout << compare(1, 2, 3) << std::endl;

    return 0;
 }

This is what I get under Visual Studio 2013(vc120)

class std::tuple<struct std::pair<int,int>,struct std::pair<int,int>,struct std::pair<int,int> >
class std::tuple<struct std::pair<int,int>,struct std::pair<int,int>,struct std::pair<int,int> >
0
class std::tuple<int,int,int>
class std::tuple<int,int,int>
0
class std::tuple<int,int,int>
class std::tuple<int,int,int>
1

and under GCC 5.2.0

St5tupleIJSt4pairIiiES1_S1_EE
St5tupleIJSt4pairIiiES1_S1_EE
0
St5tupleIJiiiEE
St5tupleIJiiiEE
0
St5tupleIJiiiEE
St5tupleIJiiiEE
1

Why are the first two is_same false and the last one true;


Solution

  • In first two cases the types that you compare using std::is_same have different const qualifications. std::is_same gives true only if given types are the same and they have the same const-volatile qualifications. See http://en.cppreference.com/w/cpp/types/is_same

    For example:

    static const auto TupleInts =
         std::make_tuple(
            1,
            2,
            3
        );
    
    typedef decltype(TupleInts) TupleIntsType;
    
    template<typename... Ts>
    bool compareIntsTuple(Ts... vals) {
            std::cout << typeid(std::tuple<Ts...>).name() << std::endl;
        std::cout << typeid(TupleIntsType).name() << std::endl;
    
        return std::is_same < std::tuple<Ts...>, TupleIntsType >::value;
    }
    

    TupleInts is declared as const and in function compareIntsTuple it is compared to std::tuple which isn't const.