Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Type traits to distinguish with typedef and without typedef

25 views
Skip to first unread message

Daniel

unread,
Aug 5, 2016, 9:25:24 AM8/5/16
to
Consider

class U
{
};

class V
{
};

class X
{
public:
typedef U u_t;
};

class Y
{
public:
typedef U u_t;
typedef V v_t;
};

How to distinguish trait class specializations for classes X and Y
(when using the default isn't an option)?

// primary template
template<class T, class Enable = void>
struct A {
A()
{
std::cout << "default" << std::endl;
}
};

// Matches Y
template <class T>
class A<T,typename std::enable_if<std::is_same<typename T::u_t,U>::value &&
std::is_same<typename T::v_t,V>::value>::type> {
public:
A()
{
std::cout << "has u_t and v_t" << std::endl;
}
};

// How to fix this to match just X?
template <class T>
class A<T,typename std::enable_if<std::is_same<typename T::u_t,U>::value>::type> {
public:
A()
{
std::cout << "has u_t but not v_t" << std::endl;
}
};

Thanks,
Daniel

Daniel

unread,
Aug 5, 2016, 11:39:48 AM8/5/16
to
On Friday, August 5, 2016 at 9:25:24 AM UTC-4, Daniel wrote:

This is my attempt (comments welcome):

class U
{
};

class V
{
};

template<class T, class Enable = void>
struct S
{
typedef void v_t;
};

template <class T>
struct S<T,typename std::enable_if<std::is_same<typename T::v_t,V>::value>::type>
{
};

class X
{
typedef U u_t;
};

class Y
{
typedef U u_t;
typedef V v_t;
};

// primary template
template<class T, class Enable = void>
struct A
{
A()
{
std::cout << "default" << std::endl;
}
};

template <class T>
struct A<T,typename std::enable_if<std::is_same<typename T::u_t,U>::value &&
std::is_same<typename T::v_t,V>::value>::type>
{
A()
{
std::cout << "has u_t and v_t" << std::endl;
}
};

template <class T>
struct A<T,typename std::enable_if<std::is_same<typename T::u_t,U>::value &&
std::is_void<typename S<T>::v_t>::value>::type>
{
A()
{
std::cout << "has u_t but not v_t" << std::endl;
}
};

int main()
{
A<X> a; // has u_t but not v_t
A<Y> b; // has u_t and v_t
A<int> c; // default
}

Öö Tiib

unread,
Aug 5, 2016, 11:56:10 AM8/5/16
to
On Friday, 5 August 2016 16:25:24 UTC+3, Daniel wrote:
> Consider
>
> class U
> {
> };
>
> class V
> {
> };
>
> class X
> {
> public:
> typedef U u_t;
> };
>
> class Y
> {
> public:
> typedef U u_t;
> typedef V v_t;
> };
>
> How to distinguish trait class specializations for classes X and Y
> (when using the default isn't an option)?

When instantiating a default (not specialization) is error then declare it
but don't define or put 'static_assert' in it.

>
> // primary template
> template<class T, class Enable = void>
> struct A {
> A()
> {
> std::cout << "default" << std::endl;
> }
> };
>
> // Matches Y
> template <class T>
> class A<T,typename std::enable_if<std::is_same<typename T::u_t,U>::value &&
> std::is_same<typename T::v_t,V>::value>::type> {
> public:
> A()
> {
> std::cout << "has u_t and v_t" << std::endl;
> }
> };
>
> // How to fix this to match just X?
> template <class T>
> class A<T,typename std::enable_if<std::is_same<typename T::u_t,U>::value>::type> {
> public:
> A()
> {
> std::cout << "has u_t but not v_t" << std::endl;
> }
> };

That is simple:

template <class T>
class A<T,typename std::enable_if<std::is_same<T,X>::value>::type> {

Fixed? That implements what comment tells (enables to match just X).

If that actually was not it then I am no psychic so I don't know what conditions you actually had in mind. On any case you can use all inbuilt
operators (like ! or ||) in that 'enable_if' to express exact set of
conditions that you want to enable since all of those are 'constexpr'.

One library in what lot of things you seem to be interested in are
implemented in generic manner is Boost Type Traits Introspection (or may
be called "Boost.TTI", I'm not sure). So it, its code or its documentation
can save you some time or at least give valuable insights.

Daniel

unread,
Aug 5, 2016, 12:24:42 PM8/5/16
to
On Friday, August 5, 2016 at 11:56:10 AM UTC-4, Öö Tiib wrote:
>
> When instantiating a default (not specialization) is error then declare it
> but don't define or put 'static_assert' in it.

In this particular case I don't want it to be an error, though.
>
> That is simple:
>
> template <class T>
> class A<T,typename std::enable_if<std::is_same<T,X>::value>::type> {
>
> Fixed? That implements what comment tells (enables to match just X).

It's a less general solution to what I proposed, though, as it only works
for class X, and not other classes that have typedefs

typedef U u_t;
typedef V v_t;

> One library in what lot of things you seem to be interested in are
> implemented in generic manner is Boost Type Traits Introspection (or may
> be called "Boost.TTI", I'm not sure). So it, its code or its documentation
> can save you some time or at least give valuable insights.

That's a good suggestion, thanks.

Best regards,
Daniel

0 new messages