Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-type class template argument deduction

I declared a template class which takes a size_t template argument. Here is the class (or struct in this case):

typedef unsigned char byte;

template <size_t NumBytes>
struct Field
{
    bool is_set = false;
    std::array<byte, NumBytes> data;

    Field() = default;
    Field(byte &&val, bool is_set = false);
    Field(std::initializer_list<byte> predef);
};

The idea is to use it for file header fields (ELF in this case). I want to be able to define a field in the following way:

const Field EI_MAG = {0x7F, 0x45, 0x4c, 0x46};

And have it automatically deduce the template argument NumBytes, such that, in this case, EI_MAG would be of type const Field<4>. The compiler complains a lot (of course) and I eventually get to the point of defining a template deduction guide. My best (and latest) attempt is the following:

template <class Type, class... Data>
Field(Type, Data...) -> Field<sizeof...(Data)>;

But the compiler still complains with the following error:

error: invalid use of template-name ‘Field’ without an argument list
   53 |     const Field EI_MAG          = {0x7F, 0x45, 0x4c, 0x46};
      |           ^~~~~

So how should I do it? Is it even possible? If not, how does std::array do it? I've been banging my head for several hours, and I still struggle a bit with how template deduction and template deduction guides work. Any help would be much appreciated.

NOTE: All the code presented is located in a .hpp file , and all struct function definitions are located in the corresponding .cpp file, which is not presented here.

like image 339
NelsonTheLotus Avatar asked Oct 21 '25 23:10

NelsonTheLotus


1 Answers

This compiles after the deduction guide is fixed.

#include <array>
#include <cstddef>

typedef unsigned char byte;

template <size_t NumBytes>
struct Field {
  bool is_set = false;
  std::array<byte, NumBytes> data;

  Field() = default;
  Field(byte &&val, bool is_set = false);
  Field(std::initializer_list<byte> predef);
};

template <class... Data>
Field(Data...) -> Field<sizeof...(Data)>;

const Field EI_MAG = {0x7F, 0x45, 0x4c, 0x46};

It doesn't need class Type.

like image 134
273K Avatar answered Oct 23 '25 15:10

273K