[英]How do I get access to template parameters of a template pack parameter
我正在尝试创建一个模板类,使比较函数返回整数[0-相等,> 0 a首先出现,<0 b首先出现]。
我正在使用Sort structs模板参数来跟踪应使用的类型,字符串中字段的偏移量以及应保留该字段的顺序...以便比较可以根据返回正确的值。
现在假设std::string
用于表示序列化值。
我在从模板中提取信息时遇到麻烦。 我将sort
保留为pack参数,其类型为Sort
。 如何在代码中访问这些参数? 如果有更好的方法来重构它。 我看了一些与模板有关的其他问题,但没有发现任何可以解决此问题的问题。 我正在使用gcc 8.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)));
}
}
};
我无法完成的两件事。
我将在另一个方面解决这个问题:如果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
做什么? 好吧,如果您可以使用简单类型T
,那么您甚至不需要模板template参数,从而使您的界面更加灵活:
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
}
};
这也增加了一天添加另一种可能具有不同模板参数或暴露出不同事物的可能性。
如果不使用这种形式,这将变得非常容易:
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
实例化,但实际上您正在接受类模板 ...例如Comparator<32, Sort, Sort, Sort>
。 大概没有意义。
但是,当我们以这种方式进行操作时,我们不仅只接受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)
依此类推。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.