代码之家  ›  专栏  ›  技术社区  ›  Hymir

派生类型名

  •  1
  • Hymir  · 技术社区  · 7 年前

    我有很多不同的函数,它们执行非常类似的操作,其中类型和大小通过如下函数名进行编码:

    int * operation_0_0_i( int a ) {
       int * result = new int[4];
       /* ... */
       return result;
    }
    int * operation_0_1_i( int a ) {
       int * result = new int[8];
       /* ... */
       return result;
    }
    
    float * operation_0_0_f( float a ) {
       float * result = new float[4];
       /* ... */
       return result;
    }
    
    float * operation_0_1_f( float a )  {
       float * result = new float[4];
       /* ... */
       return result;
    }
    

    我没有使用这么多令人困惑的不同函数,而是考虑使用模板。我第一次尝试使用模板结构来实现派生类型:

    template< typename T >
    struct A {
      using type = T;
      using array = std::array< T, 4 >;
    };
    
    template< typename T >
    struct B {
       using type = T;
       using array = std::array< T, 8 >;
    };
    

    所以我可以这样做:

    template< class U, typename T >
    T* operation0( T a ) {
      typename U<T>::array a; 
      /* ... */
      return a.data();   // I know, that this is unsafe. Its just for this example                                                                                    
    }
    
    template< class U, typename T >
    T* operation1( T a ) {
      typename U<T>::array a;                                                                                     
      /* ... */
      return a.data();
    }
    
    int main() {
       int * res1 = operation1<A, int>( 3 );
       int * res2 = operation2<B, int>( 8 );
       /* ... */
       return 0;
    }
    

    不幸的是,这无法编译。g++告诉我

    In function ‘T* operation0(T)’: error: expected nested-name-specifier before ‘U’ typename U<T>::array a;
    

    显然,typename说明符在这个位置是错误的。但是如果我删除这个说明符,g++会抱怨

    ‘U’ is not a template U<T>::array a;
    

    有人知道我做错了什么吗?有没有更好的方法,也许是使用 std::variant ? 感谢您抽出时间;)

    1 回复  |  直到 7 年前
        1
  •  3
  •   OznOg    7 年前

    您需要告诉您的U类是模板,并取1个参数:

    template<template <class > class U, typename T >
    T* operation0( T _a ) {
      typename U<T>::array a;
      /* ... */
      return a.data();                                                              
    }