我有一堂课
struct Foo {
vector<float> data;
};
并且我有一个采用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 ...
}
如果T为常数,如何将ptr设为const float *
?我了解add_const
和is_const
,但是在这里看不到如何使用它们。 (我的实际结构更加复杂,我无法直接访问其内部;它实际上是OpenCV cv::Mat
。)
如果需要,我可以使用最新的(C ++ 14 / C ++ 17)功能。
我将这样使用它:
Foo foo1 = Foo();
f(foo1); // modifiable in f
const Foo cfoo = Foo();
f(cfoo); // const, should not be modifiable in f
答案 0 :(得分:10)
最有可能的是,您实际上只想要表达式&arg.data[0]
的类型,就可以使用decltype
。
您也可以使用std::conditional
来区分大小写。
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 ...
}
如果您有第二个类型参数float *
而不是U
,则应包含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 ...
}
我已标记出C ++ 14和C ++ 17在同等用途下具有更好的语法。 C ++ 11缺少模板using
和模板变量会导致冗长的类型函数:(。
答案 1 :(得分:3)
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> >;
现在
template<typename T>
void f(T& arg) {
using ftype = transcribe_cv_t<T, float>*;
ftype ptr = &arg.data[0];
// ... do stuff with ptr ...
}
执行您的要求(还有更多)。