简体   繁体   English

c++模板,如何将map模板参数转为其他模板参数

[英]c++ templates, how to map template parameters to other template parameters

Can I somehow make a map of template parameters?我能以某种方式制作 map 的模板参数吗? let's say I have the following function:假设我有以下 function:

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);

now, let's say I don't want to call SomeFunc<T>(i) but instead, if T==float, I want to use SomeFunc<float> , if T==double I want to use SomeFunc<double> , but if T==Vector3d I don't want to use SomeFunc<Vector3d> but instead SomeFunc<double>现在,假设我不想调用SomeFunc<T>(i)但相反,如果 T==float,我想使用SomeFunc<float> ,如果 T==double 我想使用SomeFunc<double> ,但是如果 T==Vector3d 我不想使用SomeFunc<Vector3d>而是SomeFunc<double>

now of course I could explicitely implement template <> Vector3d SumCoefficients(std::vector<Vector3d > coeffs) {... } and then make the explicit call to SomeFunc<double> , but I wonder if there is an elegant way that gives me the same result with only a single template implementation plus explicit instantiation.现在我当然可以显式地实现template <> Vector3d SumCoefficients(std::vector<Vector3d > coeffs) {... }然后显式调用SomeFunc<double> ,但我想知道是否有一种优雅的方式可以给出只有一个模板实现加上显式实例化,我得到了相同的结果。

You can use constexpr if (since C++17) to check the type.可以使用constexpr if (C++17 起)检查类型。 eg例如

template<typename T>
T SumCoefficients(const std::vector<T>& coeffs) {
  T sum = static_cast<T>(0);
  for(int i=0; i<100; ++i) {
    if constexpr (std::is_same_v<T, Vector3d>) // when T is Vector3d
      sum += SomeFunc<double>(i) * coeffs[i];
    else
      sum += SomeFunc<T>(i) * coeffs[i];
  }
  return sum;
}

The constexpr if approach is fine, but I'd like to add another solution which I think is preferable, if you have many calls to SomeFunc across your code base. constexpr if 方法很好,但我想添加另一个我认为更可取的解决方案,如果您在代码库中多次调用SomeFunc

Another advantage of my solution is that it scales better if you have many types or you need to be able to add types later because the mapping logic is encapsulated in the template specialisations rather in the calling code.我的解决方案的另一个优点是,如果您有很多类型或者您以后需要能够添加类型,它可以更好地扩展,因为映射逻辑封装在模板特化中而不是调用代码中。

I assume, what you want semantically is something like the scalar type of T :我假设,您在语义上想要的是T的标量类型:

template<typename T>
struct scalar_type {

    using type = T;
};

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

Now you can add sepcializations of this template for all types of vectors or matrices or whatever you need.现在您可以为所有类型的向量或矩阵或您需要的任何类型添加此模板的专业化。

template<>
struct scalar_type<Vector3d> {

    using type = double;
};

Your calling code would look like this:您的调用代码如下所示:

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;
}

If you're restricted to c++11, the call site could look like this:如果您被限制为 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;
}

See full example here在此处查看完整示例

You asked for a C++11 solution, which can't use if constexpr :您要求提供 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;
}

(I made some assumptions on return type of SomeFunc and maybe something else, as your question didn't have full details, but I hope this will work for you) (我对SomeFunc的返回类型做出了一些假设,也许还有其他假设,因为您的问题没有完整的细节,但我希望这对您有用)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM