Reputation: 37884
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
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
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