如何访问模板包参数的模板参数

How do I get access to template parameters of a template pack parameter

本文关键字:参数 何访问 包参数 访问      更新时间:2023-10-16

我正在尝试创建一个模板类,该类将使比较函数能够返回一个整数[0-equal,>0 a应该先到,<0 b应该先到]。

我正在使用排序结构模板参数来跟踪应该使用的类型、字符串中字段的偏移量以及该字段应该保留的顺序。。。所以比较可以根据返回正确的值。

现在假设std::string用于表示序列化的值。

我在从模板中提取信息时遇到问题。我保留了sort作为一个pack参数,它的类型是Sort。如何访问代码中的这些参数?如果有更好的方法来重构它。我研究了一些与模板相关的其他问题,但没有发现任何能解决这个问题的问题。我使用的是gcc8.2和c++17。

#include <cstdint>
#include <string>
#include <cstring>
#include <cassert>
template<typename T, uint32_t offset, char Order = 'A'>
struct Sort {};
template<uint32_t keyLength, template<typename T,uint32_t offset, char Order> class ... sort>
class Comparator {
public:
int compare(std::string & a, std::string &b) {
assert(a.length()==b.length());
// How would I sum the sizeof each T. i.e. if T is int and another T is short, then sum should be 6+keyLength?
assert(a.length()==(sizeof(T)+keyLength)); // Check that my length is equal to key length + all type lengths put together
auto r = memcmp(a.data(),b.data(),keyLength);
if(r!=0) return r;
// How do I retrieve T,offset,Order of each pack parameter.
return internal_compare<T,offset,Order>(a.data(),b.data())? internal_compare<T,offset,Order>(a.data(),b.data()) : ...;
}
private:
template<typename IT,uint32_t iOffset, char iOrder>
int internal_compare(char * a,char *b) {
if constexpr (iOrder=='A'||iOrder=='a') {
return (*(static_cast<IT *>(a+iOffset)))-(*(static_cast<IT *>(b+iOffset)));
} else {
return (*(static_cast<IT *>(b+iOffset)))-(*(static_cast<IT *>(a+iOffset)));
}
}
};

有两件事我没能完成。

  • 一个是从排序中得到sizeof(T)的和
  • 对每个排序调用内部比较运算符

链接到编译器资源管理器上的代码

如果不使用以下形式,这将变得非常容易:

template<typename T, uint32_t offset, char Order = 'A'>
struct Sort {};
template<uint32_t keyLength, template<typename T,uint32_t offset, char Order> class ... sort>
class Comparator;

你用这个:

template <uint32_t keyLength, class...>
class Comparator;
template <uint32_t keyLength, typename... T, uint32_t... offset, char... Order>
class Comparator<keyLength, Sort<T, offset, Order>...> {
// ...
};

首先,原作并没有做你想做的事。您想要Sort的特定实例化,但实际上您接受了类模板。。。如CCD_ 5。这大概没有什么意义。

但当我们这样做的时候,我们不仅只接受Sort的实例化,而且我们有最有用的形式的参数

// How would I sum the sizeof each T. i.e. if T is int and another T is short,
// then sum should be 6+keyLength?

是折叠表达式:

(sizeof(T) + ... + keyLength)

等等。

我将从另一个方面来解决这个问题:如果T有模板参数,如何提取模板参数?这里有一个例子:

template<typename T>
void foo(T v) {
// T is std::vector<int>, how to extract `int`?
}
int main() {
foo(std::vector{1, 2, 3, 4});
}

对此有很多答案:使用部分专业化提取、键入别名等。

以下是如何为std::vector:执行此操作

template<typename>
struct extract_value_type_t {};
template<typename T>
struct extract_value_type_t<std::vector<T>> {
using type = T;
};
template<typename T>
using extract_value_type_t = typename extract_value_type<T>::type;
template<typename T>
void foo(T v) {
// with template specialization
using value_type = extract_value_type_t<T>;
// with the member alias std::vector exposes
// needs much less boilerplate!
using value_type = typename T::value_type;
}

T是一个向量时,它给我们带来了什么?好吧,如果你可以用一个简单的类型T做一些事情,你甚至不需要模板模板参数,这会使你的界面更加灵活:

template<typename>
struct sort_traits {};
template<typename T, uint32_t offset_, char order_>
struct sort_traits<Sort<T, offset_, order_>> {
using type = T
static constexpr auto offset = offset_;
static constexpr auto order = order_;
};

然后在你的Comparator类中,简单地做一些类似的事情:

template<uint32_t keyLength, typename... sorts>
struct Comparator {
int compare(std::string const& a, std::string const& b) {
return (internal_compare<sorts>(a.data(), b.data()) && ...);
}
private:
template<typename sort>
int internal_compare(char const* a, char const* b) {
using traits = sort_traits<sort>;
using type = typename traits::type;
constexpr auto offset = traits::offset;
constexpr auto order = traits::order;
// do stuff
}
};

这也增加了有一天添加另一种排序的可能性,这种排序将具有不同的模板参数或不同的内容。