Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strong typedefs [duplicate]

Is there any way to make a complete copy of a type so that they can be distinguished in template deduction context? Take the example:

#include <iostream>

template <typename T>
struct test
{
    static int c()
    { 
        static int t = 0;
        return t++;
    }
};

typedef int handle;

int main()
{
    std::cout << test<int>::c() << std::endl;
    std::cout << test<handle>::c() << std::endl;
    return 0;
}

Since typedef only makes an alias for a type, this prints 0, 1 instead of the desired 0, 0. Is there any workaround for this?

like image 257
Veritas Avatar asked Mar 07 '15 15:03

Veritas


2 Answers

Quoting cplusplus.com,

Note that neither typedef nor using create new distinct data types. They only create synonyms of existing types. That means that the type of myword above, declared with type WORD, can as well be considered of type unsigned int; it does not really matter, since both are actually referring to the same type.

Since int and handle are one and the same, the output 0 1 is expected.

There's a workaround though, as @interjay suggests.

You can use BOOST_STRONG_TYPEDEF.

BOOST_STRONG_TYPEDEF( int , handle );
like image 117
shauryachats Avatar answered Nov 15 '22 18:11

shauryachats


Either as suggested BOOST_STRONG_TYPEDEF

template<typename>
struct test {
    static int c() {
        static int t = 0;
        return t++ ;
    } 
};

//Instead of 
//typedef int handle

BOOST_STRONG_TYPEDEF(int , handle) ;  

int main() {

    std::cout << test<int>::c() << std::endl
    std::cout << test<handle>::c() << std::endl ;
    return 0;
}

Output : 0 0 , because handle is not int but a type implicitly convertable to int .

if you don't want to use BOOST_STRONG_TYPE then simply add second parameter to your class template :

template<typename, unsigned int N>
struct test {
    static int c() {
        static int t = 0;
        return t++ ;
    }

};

Thus making test<int, 0> and test<handle, 1> different types

int main() {

    std::cout << test<int, 0>::c() << std::endl ;
    std::cout << test<handle,1>::c() << std::endl ;
    return 0;
} 

Output : 0 0

You can also add macro to generate your types :

#define DEFINE_TEST_TYPE(type) \
typedef test<type, __COUNTER__> test_##type;


template<typename, unsigned int N>
struct test {    
     static int c() {
        static int t = 0;
        return t++ ;   
    }
};

typedef int handle ;

DEFINE_TEST_TYPE(int) ;
DEFINE_TEST_TYPE(handle) ;

int main() {
    std::cout << test_int::c() << std::endl ;
    std::cout << test_handle::c() << std::endl ;
    return 0;
}
like image 23
Vladimir Venediktov Avatar answered Nov 15 '22 20:11

Vladimir Venediktov