c ++模板,如何将模板参数映射到其他模板参数

时间:2020-08-04 08:49:53

标签: c++ templates

我可以以某种方式制作模板参数图吗?假设我具有以下功能:

template<typename T>
T SumCoefficients(const std::vector<T>& coeffs) {
  T sum = static_cast<T>(0);
  for(int i=0; i<100; ++i) {
    sum += SomeFunc<T>(i) * coeffs[i];
  }
  return sum;
}

// explicit instantiation

template double SumCoefficients(const std::vector<double>& coeffs);
template float SumCoefficients(const std::vector<float>& coeffs);
template Vector3d SumCoefficients(const std::vector<Vector3d >& coeffs);

现在,假设我不想呼叫SomeFunc<T>(i),但是,如果T == float,我想使用SomeFunc<float>,如果T == double,我想使用{{1 }},但是如果T == Vector3d,我不想使用SomeFunc<double>,而是使用SomeFunc<Vector3d>

现在我当然可以显式实现SomeFunc<double>,然后显式调用template <> Vector3d SumCoefficients(std::vector<Vector3d > coeffs) { ... },但是我想知道是否有一种优雅的方法仅用一个模板实现就可以得到相同的结果显式实例化。

3 个答案:

答案 0 :(得分:3)

您可以使用constexpr if(从C ++ 17开始)检查类型。例如

writeRaster()

答案 1 :(得分:3)

constexpr if方法很好,但是如果您在代码库中多次调用SomeFunc,我想添加另一个我认为更可取的解决方案。

我的解决方案的另一个优点是,如果您有很多类型,或者以后需要添加类型,它的伸缩性会更好,因为映射逻辑封装在模板专用语言中,而不是在调用代码中。

我认为,您在语义上想要的是类似T的标量类型的东西:

template<typename T>
struct scalar_type {

    using type = T;
};

template<typename T>
using scalar_t = typename scalar_type<T>::type;

现在,您可以为所有类型的向量或矩阵或您需要的任何内容添加此模板的分隔符。

template<>
struct scalar_type<Vector3d> {

    using type = double;
};

您的调用代码如下:

template<typename T>
auto SumCoefficients(const std::vector<T>& coeffs) {
  scalar_t<T> sum;
  for(int i=0; i<100; ++i) {
    sum += SomeFunc<scalar_t<T>>(i) * coeffs[i];
  }
  return sum;
}

如果您仅限使用c ++ 11,则呼叫站点可能如下所示:

template<typename T, typename Scalar = scalar_t<T>>
Scalar SumCoefficients(const std::vector<T>& coeffs) {
  Scalar sum;
  for(int i=0; i<100; ++i) {
    sum += SomeFunc<Scalar>(i) * coeffs[i];
  }
  return sum;
}

查看完整示例here

答案 2 :(得分:2)

您要求使用C ++ 11解决方案,该解决方案不能使用if constexpr

template<typename T>
T SumCoefficients(const std::vector<T>& coeffs) {
  using TTag = typename std::conditional<std::is_same<T, Vector3d>::value, double, T>::type;
  TTag sum = static_cast<TTag>(0);
  for(int i=0; i<100; ++i) {
    sum += SomeFunc<TTag>(i) * coeffs[i];
  }
  return sum;
}

(我对SomeFunc的返回类型做了一些假设,也许还有其他一些假设,因为您的问题没有完整的细节,但我希望这对您有用)