依赖于模板参数的成员函数实现

member function implementation depending on template parameter

我有以下问题:

template< typename T, size_t N, size_t... N_i >
class A
{  
  public:

    // ...

    // first implementation
    template< size_t M = sizeof...(N_i)+1, typename std::enable_if< M!=1, size_t >::type = 0 >
    A<T, N_i...> operator[]( size_t i )
    {
      A< T, N_i... > res{ ... };

      return res;
    }

    // second implementation
    template< size_t M = sizeof...(N_i)+1, typename std::enable_if< M==1, size_t >::type = 0 >
    T operator[]( size_t i )
    {
      return ... ;
    }
};

正如你在上面看到的,我尝试实现一个 class A ,它期望作为模板参数类型 T (例如 intfloat) 和 sizeof...(N_i)+1-许多 size_t.

根据传递的数量size_t(即sizeof...(N_i)+1),我将对具有不同结果类型的成员函数operator[](size_t)使用不同的实现:

不幸的是,我不知道如何实现——上面的解决方案不起作用。有人有想法吗?

非常感谢。

如果修改

A< T, N_i... > res{ ... };

A< T, N_i... > res{ };

return ... ;

return T{} ;

还不够吗?

--- 编辑 ---

否:正如 Jarod42 所指出的(谢谢!),这还不够。

所以我提出以下解决方案,基于class模板专业化和std::conditional以避免使用SFINAE

#include <iostream>
#include <type_traits>

template< typename, size_t...>
class A;

template< typename T, size_t N, size_t... N_i >
class A<T, N, N_i...>
 {  
   public:
      template <typename Next = typename std::conditional<sizeof...(N_i),
                                           A<T, N_i...>, T>::type>
      Next operator[] (size_t i)
       { return Next{}; }
 };

int main(int argc, char* argv[]) 
 {
   A<int, 2, 4> a;

   std::cout << a[1][2] << std::endl;

   return 0;
 }

如果你不想专门化 A,你可以添加一个 A 的子结构来完成脏活。

#include <iostream>
#include <type_traits>

template< typename T, size_t N, size_t... N_i >
class A
 {  
   template <typename U, size_t ... O_i>
      struct Next
       { using type = A<U, O_i...>; };

   template <typename U>
      struct Next<U>
       { using type = U; };

   public:
      using next_t = typename Next<T, N_i...>::type;

      next_t operator[] (size_t i)
       { return next_t{}; }
 };

int main(int argc, char* argv[]) 
 {
   A<int, 2, 4> a;

   std::cout << a[1][2] << std::endl;

   return 0;
 }

A<T, N_i...> 对空 N_i 无效。 作为解决方法,您可以使用间接寻址:

template <typename, std::size_t ...>
struct PopFrontA
{
    using type = void; // Dummy type for A<T, N>
};

template< typename T, std::size_t N, std::size_t... N_i > class A;

template <typename T, std::size_t N, std::size_t N2, std::size_t ... Ns>
struct PopFrontA<T, N, N2, Ns...>
{
    using type = A<T, N2, Ns...>;
};

template <typename T, std::size_t ... Ns>
using PopFrontA_t = typename PopFrontA<T, Ns...>::type;

然后

// first implementation
template< size_t M = sizeof...(N_i)+1, typename std::enable_if< M!=1, size_t >::type = 0 >
PopFrontA_t<T, N, N_i...>
operator[]( size_t i )
{
  A< T, N_i... > res{ /*...*/ };

  return res;
}

Demo