如何获得访问模板包参数模板参数

问题描述 投票:1回答:2

我想创建一个模板类,使比较函数返回一个整数[ - 等于,> 0应该先,<0 B应该放在第一位。

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

现在假设该std::string用来表示一个序列化值。

我有提取模板信息的麻烦。我一直sort作为包参数,这将是类型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)));
         }
      }
};

两件事情我一直没能实现。

  • 一个越来越的sizeof(T)从排序的总和。
  • 调用每个类型的内部比较运营商。

Link to code on compiler explorer

c++ templates c++17
2个回答
2
投票

此变得基本上更容易的,如果不是使用这种形式:

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)

等等。


2
投票

我会采取另一条战线这个问题:你如何提取模板参数,如果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
    }
};

这也增加了可能性,一天增加了另一种形式的,将有不同的模板参数或暴露的不同的事情。

© www.soinside.com 2019 - 2024. All rights reserved.