Trevor Hickey
Trevor Hickey

Reputation: 37884

How do I write a "pointer to const" type trait?

I'm looking for the following results:

/* true */  std::cout << ptr_to_const_v<const int*> << '\n';
/* true */  std::cout << ptr_to_const_v<const int*const> << '\n';
/* false */ std::cout << ptr_to_const_v<int*> << '\n';
/* false */ std::cout << ptr_to_const_v<int*const> << '\n';

Here is my attempt at a type trait:

template <typename T>
struct ptr_to_const : std::is_const<std::remove_pointer<T>> {};

This gives all false.

Alternatively,

template <typename T>
struct ptr_to_const : std::is_const<const std::remove_pointer<T>> {};

This gives all true.

I suppose this is because const is a qualifier of the type, and not part of the type itself.
What can I do?

Upvotes: 1

Views: 869

Answers (2)

Qaz
Qaz

Reputation: 61970

You're checking the type of the std::remove_pointer type trait, not the type with that trait applied.

C++14:

template <typename T>
struct ptr_to_const : std::is_const<std::remove_pointer_t<T>> {};
                                                       ^^

Older:

template <typename T>
struct ptr_to_const : std::is_const<typename std::remove_pointer<T>::type> {};
                                    ^^^^^^^^^                      ^^^^^^

However, since you simply remove the pointer, you cannot tell whether T was originally a pointer or not, making the trait too permissive. Since you labelled this C++1z, you can use std::conjunction, which is basically a short-circuiting metaprogramming &&:

template <typename T>
struct ptr_to_const : std::conjunction<
    std::is_pointer<T>, 
    std::is_const<std::remove_pointer_t<T>>
> {};

You could also opt for a C++1z bool_constant and use &&, although this does not do short-circuiting.

Upvotes: 5

T.C.
T.C.

Reputation: 137425

template<class T>
using ptr_to_const = std::conjunction<std::is_pointer<T>, 
                                      std::is_const<std::remove_pointer_t<T>>>;

Upvotes: 1

Related Questions