在 C++ class 模板中表示空类型

Represents empty type in C++ class template

考虑以下 compile-time“矢量”示例。

#include <iostream>

template <int n, int...ns>
struct static_vector {
    static constexpr int value = n;
    static_vector<ns...> rest;
};

template <int n>
struct static_vector<n> {
    static constexpr int value = n;
    void* rest;
};

template <int n, class sv>
constexpr int access_nth() {
    static_assert(n >= 0, "vector size out of bound");
    if constexpr(n == 0) {
        return sv::value;
    } else {
        static_assert(!std::is_same_v<decltype(sv::rest), void *>, "vector size out of bound");
        return access_nth<n-1, decltype(sv::rest)>();
    }
}

int main()
{
    constexpr auto a = static_vector<12, 23, 34, 45>();
    constexpr int nth = access_nth<5, decltype(a)>();
    std::cout << nth << std::endl;
}

我对我们现在可以做的非常满意:定义一个向量,然后从中获取第 n 个元素。我发现不满意的一件事是:我必须在基本情况下使用 void * 作为虚拟对象(其中向量只包含一个元素而没有尾巴......)

我试过这样的专业:

template <>
struct static_vector<> {
}

表示空向量。但似乎编译器总是拒绝此定义并出现以下错误:

<source>:16:8: error: too few template arguments for class template 'static_vector'

struct static_vector<> {

       ^

我应该怎么做才能得到一个空向量?

非常感谢。

特化必须符合基本模板声明。由于基本模板至少需要一个 int,因此无法编译。

您可以通过声明模板采用任意数量的 int 参数,然后专门化采用一个或多个参数的每个案例来实现此目的。基本声明就是空的情况:

template <int...>
struct static_vector {
    // Instantiated only for the no-argument case
};

template <int n>
struct static_vector<n> {
    // One-argument specialization
};

template <int n, int... ns>
struct static_vector<n, ns...> {
    // Two-or-more-argument specialization
};

但为什么要递归?

你标记了 C++17 以便你可以使用模板折叠,所以...下面怎么样?

#include <iostream>

template <int ... Is>
struct static_vector
 {
   template <std::size_t N>
   int get () const
    {
      static_assert( N < sizeof...(Is), "index out of bound" );

      std::size_t i{};
      int ret;

      ( ... , (N == i++ ? ret = Is : 0) );

      return ret;
    }
 };


int main()
 {
   constexpr auto a = static_vector<12, 23, 34, 45>();

   std::cout << a.get<3u>() << std::endl;
 }