Reputation: 6338
I have a class:
struct Foo {
vector<float> data;
};
and I have a templated function that takes a Foo&:
template<typename T>
void f(T& arg) {
using ftype = float *; // <-- would like this to be const float * if T is const
ftype ptr = &arg.data[0];
// ... do stuff with ptr ...
}
How can I make ptr be const float *
iff T is const? I know about add_const
and is_const
but don't see how to use them here. (My real struct is more complicated and I don't have direct access to its internals; it's actually an OpenCV cv::Mat
.)
I can use recent (C++14/C++17) features if needed.
I'll use it like this:
Foo foo1 = Foo();
f(foo1); // modifiable in f
const Foo cfoo = Foo();
f(cfoo); // const, should not be modifiable in f
Upvotes: 13
Views: 3280
Reputation: 62636
Most likely, you actually just want the type of the expression &arg.data[0]
, for which you can use decltype
.
You can also use std::conditional
to distinguish the cases.
template<typename T>
void f(T& arg) {
// C++17: using ftype = std::conditional_t<std::is_const_v<T>, const float *, float *>;
using ftype = typename std::conditional<std::is_const<T>::value, const float *, float *>::type;
ftype ptr = &arg.data[0];
// ... do stuff with ptr ...
}
If instead of float *
, you had a second type parameter U
, you would include std::add_const
template<typename T, typename U = float *>
void f(T& arg) {
// C++17: using ftype = std::conditional_t<std::is_const_v<T>, std::add_const_t<U>, U>;
using ftype = typename std::conditional<std::is_const<T>::value, typename std::add_const<U>::type, U>::type;
// ... do stuff with ftype ...
}
I have marked where C++14 and C++17 has nicer syntax for equivalent use. C++11 lack of template using
s and template variables results in verbose type functions :(.
Upvotes: 14
Reputation: 275385
template<class Src, class Dst>
using transcribe_const_t = std::conditional_t<std::is_const<Src>{}, Dst const, Dst>;
template<class Src, class Dst>
using transcribe_volatile_t = std::conditional_t<std::is_volatile<Src>{}, Dst volatile, Dst>;
template<class Src, class Dst>
using transcribe_cv_t = transcribe_const_t< Src, transcribe_volatile_t< Src, Dst> >;
now
template<typename T>
void f(T& arg) {
using ftype = transcribe_cv_t<T, float>*;
ftype ptr = &arg.data[0];
// ... do stuff with ptr ...
}
does what you ask (and a bit more).
Upvotes: 4