【问题标题】:How to declare a variable whose type is the generics of another object?如何声明一个类型是另一个对象的泛型的变量?
【发布时间】:2021-04-21 15:06:31
【问题描述】:

考虑以下一段 C++ 代码:

int main(){
  MyObject<int> obj;
  foo(obj);
}
template <typename T>
void foo(T& objct){
...
}

在 foo 中,objct 的类型将是 MyObject&lt;int&gt;
我想在foo() 中创建一个变量,其类型是objct 的泛型,在本例中为int
有没有办法做到这一点?谢谢。

编辑 不幸的是(我认为)我无法重写签名,因为函数foo() 是用不同类型的对象调用的,例如

int main(){
  MyObject<int> obj;
  MyDifferentObject<int> obj2;
  foo(obj);
  foo(obj2);
}

【问题讨论】:

  • 如果MyObject 遵循良好的做法,它有一个MyObject::value_type 或类似的。 MyObject 是什么?
  • template &lt;typename T&gt; void foo(MyObject&lt;T&gt;&amp; objct);?
  • @largest-prime-is-463035818 MyObject 没有遵循这种做法啊,它只是我创建的一个类。
  • @jarod42 对不起,你是什么意思?上面的代码运行良好。
  • 我的意思是答案中提出的内容。

标签: c++ templates generics


【解决方案1】:

使用模板模板参数定义foo() 怎么样?

template <template <typename...> class C, typename T>
void foo (C<T> & objct)
{
  /...
}

也可以

template <template <typename...> class C, typename T, typename ... Ts>
void foo (C<T, Ts...> & objct)
{
  /...
}

更灵活,也接受带有多个模板类型参数的类型。

这样,如果你打电话

MyObject<int>  obj;
MyDifferentObject  obj2;

foo(obj);
foo(obj2); 

C 在第一种情况下是 MyObjectMyDifferentObject 在第二种情况下,T 在这两种情况下都是 int

显然,这仅适用于 foo() 的参数是只有模板类型参数的模板类的对象,例如,不适用于 std::array

std::vector<int>     v;
std::array<int, 5u>  a;

foo(v); // compile: only types parameters for std::vector
foo(a); // compilation error: a non-type template parameter for std::array

【讨论】:

    【解决方案2】:

    我想在 foo() 中创建一个变量,其类型是 objct 的泛型,在本例中为 int。 有没有办法做到这一点?

    如果您可以更改函数签名,那么您可以这样做:

    template <typename T>
    void foo(MyObject<T>& objct){
        T variable;
    

    如果这不是一个选项,例如,如果您希望 foo 也允许其他模板(例如在您编辑的问题中),那么您可以定义类型特征:

    template<class T>
    struct fancy_type_trait
    {
    };
    
    template<class T>
    struct fancy_type_trait<MyObject<T>>
    {
        using type = T;
    };
    
    template<class T>
    struct fancy_type_trait<MyDifferentObject<T>>
    {
        using type = T;
    };
    
    template <typename T>
    void foo(T& objct){
       using V = typename fancy_type_trait<T>::type;
       V variable;
    

    【讨论】:

      【解决方案3】:

      您可以编写一个 trait 来确定具有一个模板参数的模板的任何实例化的第一个模板参数:

      #include <type_traits>
      
      template <typename T>
      struct MyObject {};
      
      template <typename T>
      struct MyOtherObject {};
      
      template <typename T>
      struct first_template_parameter;
      
      template <template<typename> typename T,typename X>
      struct first_template_parameter< T<X> > {
          using type = X;
      };
      
      int main() {
          static_assert(std::is_same< first_template_parameter<MyObject<int>>::type,
                                      first_template_parameter<MyOtherObject<int>>::type>::value  );    
      
      }
      

      特征first_template_parameter 可以使用单个参数对模板进行任何实例化,并告诉您该参数是什么。 first_template_parameter&lt; MyObject&lt;int&gt; &gt;::typeint。更一般地说,first_template_parameter&lt; SomeTemplate&lt;T&gt; &gt;::typeT(假设 SomeTemplate 有一个参数)。 这是对this answer 中使用的特征的轻微概括,如果需要,它可以概括为也适用于具有多个参数的模板实例化。 在你的函数中,你会像这样使用它:

      template <typename T>
      void foo(T& objct){
          typename first_template_parameter<T>::type x;
      }
      

      【讨论】:

        猜你喜欢
        • 2013-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-23
        • 1970-01-01
        • 2020-12-05
        • 1970-01-01
        相关资源
        最近更新 更多