在C++模板中根据模板参数有条件地定义类型别名



我想按照以下行写一个模板类:

template <typename T>
struct lerp1d {
lerp1d(const T& abs_begin, const T& abs_end, const T& ord_begin, const T& ord_end) {}
auto operator()(val_t x) const -> val_t { 
// ... 
}
const std::vector<val_t> x_data_;
const std::vector<val_t> y_data_;
};

这样我就可以理想地初始化如下实例:

std::vector<double> x = /*...*/;
std::vector<double> y = /*...*/;
double *x = get_arr_x();
double *y = get_arr_y();
auto l1 = lerp1d(x.cbegin(), x.cend(), y.cbegin(), y.cend()); /* (1) */
auto l2 = lerp1d(x, x+n, y, y+n);                             /* (2) */

问题是,如何对val_t进行别名

一种选择是简单地说:

using val_t = typename T::value_type;

但这对实例(2)不起作用。尝试使用std::remove_pointer<T>std::is_pointer_v<T>std::enable_ifstd::conditional,但似乎不适用。

您可以在C++20 中使用std::iter_value_t来获取迭代器的value_type

#include <iterator>
template<std::random_access_iterator T>
struct lerp1d {
using val_t = std::iter_value_t<T>;
lerp1d(const T& abs_begin, const T& abs_end, 
const T& ord_begin, const T& ord_end) {}
auto operator()(val_t x) const -> val_t { 
// ... 
}
const std::vector<val_t> x_data_;
const std::vector<val_t> y_data_;
};

演示

按照您的设计方式,如果您提供具有相同value_t的两种不同类型的集合,它将产生两个不同的类,除了构造它们之外,它们之间没有任何不同之处。例如,在(1(中,您将构建lerp1d<std::vector<double>::iterator>,在(2(中构建lerp1d<double*>。但您对double部分感兴趣,而不是对向量或指针感兴趣。

我建议将类模板化为实际存储的类型,并为迭代器类型上的构造函数创建另一个模板。

#include <vector>
template <typename T>
struct lerp1d {
template<typename U>
lerp1d(const U& abs_begin, const U& abs_end, const U& ord_begin, const U& ord_end)
: x_data_(abs_begin, abs_end), y_data_(ord_begin, ord_end)
{}
auto operator()(T x) const -> T { 
return x; // to be implemented
}
const std::vector<T> x_data_;
const std::vector<T> y_data_;
};
static double xs[] = {3.2, 5.1, 4.8};
static double ys[] = {7.3, 5.3, 1.0};
int main(void) {
std::vector<double> vx = {3.2, 5.1, 4.8};
std::vector<double> vy = {7.3, 5.3, 1.0};
double *x = xs;
double *y = ys;
auto l1 = lerp1d<double>(vx.cbegin(), vx.cend(), vy.cbegin(), vy.cend()); /* (1) */
auto l2 = lerp1d<double>(x, x+3, y, y+3);                                 /* (2) */
}

最新更新