如果模板arg为const

时间:2018-09-28 16:24:06

标签: c++ c++11 templates

我有一堂课

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_constis_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

2 个答案:

答案 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 ...
}

执行您的要求(还有更多)。