简体   繁体   English

带有条件类型名的模板 class

[英]Template class with conditional typenames

I would like to have a template class (eg float / double type), but I am using Nvidia CUDA and OptiX and have multiple other types (eg float2 , double2 , float3 ,...) that depend on the chosen template type.我想要一个模板 class(例如float / double类型),但我使用的是Nvidia CUDAOptiX ,并且有多种其他类型(例如float2double2float3 ……),具体取决于所选模板类型。

Something like this:像这样的东西:

#include <optixu/optixu_vector_types.h>
#include <type_traits>

template <class T>
class MyClass 
{
   MyClass()
   {
      if (std::is_same<T, float>::value) 
      {
         typedef optix::float2 T2;
      }
      else if (std::is_same<T, double>::value)
      {
         typedef optix::double2 T2;
      }

      T2 my_T2_variable;
   }

   void SomeFunction() 
   { 
      T2 another_T2_variable; 
   };
};

My solution for now is to have multiple template arguments MyClass<T,T2,T3> my_object;我现在的解决方案是拥有多个模板 arguments MyClass<T,T2,T3> my_object; , but this seems to have too much overhead and clutter. ,但这似乎有太多的开销和混乱。 Is there a way to achieve the same with a single template argument as desired above?有没有一种方法可以使用上面所需的单个模板参数来实现相同的目标?

Typically you'd do this by creating a trait type whose specializations define the additional types.通常,您会通过创建其特化定义附加类型的特征类型来做到这一点。 For example:例如:

// Base template is undefined.
template <typename T>
struct optix_traits;

template <>
struct optix_traits<float> {
    using dim2 = optix::float2;
    // etc
};

template <>
struct optix_traits<double> {
    using dim2 = optix::double2;
    // etc
};

Then you can alias from these types to a name in your type, if desired:然后,如果需要,您可以从这些类型中将其别名为您的类型中的名称:

template <typename T>
class MyClass {
public:
    using T2 = typename optix_traits<T>::dim2;
};

You can use std::conditional , from <type_traits> .您可以使用std::conditional ,来自<type_traits>

If you want the T2 be optix::float2 when T == float and otherwise optix::double2 , use std::conditional .如果您希望T2T == float时为optix::float2 ,否则optix::double2 ,请使用std::conditional This is availble since and will resolve the type T2 at compile time.这是自以来可用的,并将在编译时解析类型T2

#include <type_traits>  // std::conditional, std::is_same

template <class T>
class MyClass
{
    using T2 = typename std::conditional<std::is_same<T, float>::value,
                                          optix::float2, optix::double2>::type;
    T2 my_T2_variable;

    // ... other code
};

( See demo ) 见演示


As @HikmatFarhat pointed out, std::conditional will not catch the user mistakes.正如@HikmatFarhat指出的那样, std::conditional不会捕获用户错误。 It checks only the first condition, and for the false case gives the type optix::double2 .它只检查第一个条件,对于false情况给出类型optix::double2

Another option is series of SFINAE ed functions, and decltype to those for the T2 as follows:另一个选项是一系列 SFINAE ed 函数,以及对T2decltype如下:

#include <type_traits>  // std::is_same, std::enable_if

template <class T> // uses if T == float and return `optix::float2`
auto typeReturn() -> typename std::enable_if<std::is_same<float, T>::value, optix::float2>::type { return {}; }

template <class T> // uses if T == double and return `optix::double2`
auto typeReturn() -> typename std::enable_if<std::is_same<double, T>::value, optix::double2>::type { return {}; }

template <class T>
class MyClass
{
    using T2 = decltype(typeReturn<T>()); // chooses the right function!

    T2 my_T2_variable;

    // ... other codes
};

( See demo ) 见演示

Implement a meta-function using template specialization that maps standard C++ types to OptiX types with the desired "rank":使用将标准 C++ 类型映射到具有所需“等级”的 OptiX 类型的模板特化实现元函数:

template <typename T, std::size_t N> struct optix_type;

template <> struct optix_type<float, 2> { using type = optix::float2; };
template <> struct optix_type<float, 3> { using type = optix::float3; };
template <> struct optix_type<double, 2> { using type = optix::double2; };
// ...

template <typename T, std::size_t N>
using optix_type_t = typename optix_type<T, N>::type;

You can then use this within your class(es) to easily get the right types:然后,您可以在您的课程中使用它来轻松获得正确的类型:

template <class T>
class MyClass {
  using T2 = optix_type_t<T, 2>;
  MyClass() {
    T2 my_T2_variable;
    optix_type_t<T, 3> my_T3_variable;
  }
  void SomeFunction() { T2 another_T2_variable; };
};

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

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