带有条件类型名的模板类

Sem*_*exB 19 c++ templates class class-template c++11

我想有一个模板类(如float/double类型),但我使用Nvidia的CUDAOptix公司和有多个其他类型(例如float2double2float3,...)依赖于所选择的模板类型。

像这样的东西:

#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; 
   };
};
Run Code Online (Sandbox Code Playgroud)

我现在的解决方案是有多个模板参数MyClass<T,T2,T3> my_object;,但这似乎有太多的开销和混乱。有没有办法使用上述所需的单个模板参数实现相同的目标?

cdh*_*wie 21

通常,您可以通过创建一个特征类型来实现这一点,该类型的特化定义了附加类型。例如:

// 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
};
Run Code Online (Sandbox Code Playgroud)

然后,如果需要,您可以将这些类型的别名转换为您的类型中的名称:

template <typename T>
class MyClass {
public:
    using T2 = typename optix_traits<T>::dim2;
};
Run Code Online (Sandbox Code Playgroud)

  • @SemtexB 类外成员函数定义只有在知道该成员属于什么类型之后才“在范围内”。当它看到“T2”时,它不知道“T2”是什么,因为它还不知道该方法在“MyClass&lt;T&gt;”中。全部拼写出来: `template &lt;typename T&gt; typename MyClass&lt;T&gt;::T2 MyClass&lt;T&gt;::Foo() { ... }` 从 C++11 开始,您还可以使用 `auto` 来移动返回值类型,如下所示:`template &lt;typename T&gt; auto MyClass&lt;T&gt;::Foo() -&gt; T2 { ... }`。由于在这种情况下返回类型出现在 `MyClass&lt;T&gt;::` 之后,因此它知道在 `MyClass&lt;T&gt;` 中查找它。 (2认同)

JeJ*_*eJo 15

您可以使用std::conditional, 从<type_traits>.

如果您希望T2beoptix::float2时间T == float和其他情况optix::double2,请使用std::conditional. 这从就可用,并将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
};
Run Code Online (Sandbox Code Playgroud)

见演示


正如@HikmatFarhat指出的那样,std::conditional不会发现用户错误。它只检查第一个条件,并为falsecase 给出 type optix::double2

另一种选择是系列SFINAE的编功能,以及decltype那些用于T2如下:

#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
};
Run Code Online (Sandbox Code Playgroud)

见演示

  • @HikmatFarhat 你是对的。添加了另一个选项,该选项类似于 type_trait 解决方案,应该可以解决该问题。 (3认同)

Erl*_*nig 5

使用模板特化实现元函数,将标准 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;
Run Code Online (Sandbox Code Playgroud)

然后你可以在你的类中使用它来轻松获得正确的类型:

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; };
};
Run Code Online (Sandbox Code Playgroud)