I've been beating my head against this problem for a couple days. Thought someone here might be able to shed some light.
I'm trying to build a constructor for this class so that I can easily allocate an instance of it at compile time:
template <class T>
class Selector {
const size_t number;
size_t current;
T * const list;
public:
constexpr Selector(?????): number(??), current(0), list(??) {}
T& next() {
if (++current >= number) current = 0;
return list[current];
}
};
I'd like to use what I believe is an initializer list to instantiate an instance of this class but I cannot quite figure out the right method/syntax. Basically I want to be able to do something like this:
Selector<int> order(1,7,4,0,1);
// Complicated objects should work too:
struct FooBar { int foo; int bar; };
Selector<FooBar> orderPairs({1,2}, {3,4}, {5,6});
Note, I'm really just after being able to specify a list of things and the compiler to automatically get the length of that list for me so that I can use that constant length at runtime. See next()
.
If the syntax ends up being a little different, that's fine. For instance if this is needed, that's fine:
Selector<int> order({1,7,4,0,1});
Selector<int> order = {1,7,4,0,1};
The important thing is getting the list's length automatically.
I'd also like to enforce that this can only be constructed at compile time. My understanding is that constexpr
or initializer_list
should basically do that for us.
What I've tried
initializer_list
I've tried using an initializer_list
as an argument to the constructor but can't seem to get that to work:
template <class T>
class Selector {
const size_t number;
size_t current;
T * const list;
public:
constexpr Selector(std::initializer_list<T> list): number(list.size()), current(0), list(list) {}
};
In file included from test.cpp:3:0:
test.hpp: In constructor 'constexpr Selection::Selection(std::initializer_list<Input>)':
test.hpp:27:59: error: cannot convert 'std::initializer_list<Input>' to 'Input* const' in initialization
: number(list.size()), list(list), current(0) {}
^
This makes sense to me. Need to initialize the array somehow and get the pointer to that to memory in this object. However my attempts to allocate array space have proven unfruitful:
template <class T>
class Selector {
const size_t number;
size_t current;
T * const list;
public:
constexpr Selector(std::initializer_list<T> list): number(list.size()), current(0), list(std::array<T, list.size()>(list)) {}
};
In file included from test.cpp:3:0:
test.hpp: In constructor 'Selection::Selection(std::initializer_list<Input>)':
test.hpp:28:71: in constexpr expansion of 'list.std::initializer_list<_E>::size<Input>()'
test.hpp:28:72: error: 'list' is not a constant expression
: number(list.size()), list(std::array<Input, list.size()>(list)), current(0) {}
^
I see that it is saying that list
is not constexpr
but as far as I can tell it is... Regardless I'm not exactly trying to allocate the array inside this object, just the pointer to the array. My thinking is that this is where I'm missing the simple step to allocate the array inline... but maybe this is not possible. I haven't tried using a vector
because that feels like too much overhead. Maybe I'm being naive here...
Variadic Arguments / Parameter Pack
I've also tried with with variable arguments with the ...
syntax but haven't gotten that to work.
Parameter Packs are I believe incorrect because that's a template list of varying parameters. All the elements in the list are of known type. It's the length that is unknown (albeit constant).
template <class T>
class Selector {
const size_t number;
size_t current;
T * const list;
public:
constexpr Selector(T... list): number(sizeof...(list)), current(0), list(list) {}
};
In file included from test.cpp:3:0:
test:26:34: error: expansion pattern 'Input' contains no argument packs
constexpr Selection(Input... list)
^
Parameter packs also seem to be wrong because they template the whole class based on the number of arguments. In the larger context that I'm trying to use this in, that does not work for me. Only the underlying array element type can be in the template. Specifically, I'm trying to declare that an instance of this class as extern
in one header file (not knowing the length but knowing the type) and defining it in some dependant compilation unit before linking.
Environment
I am trying to use this on an AVR system with avr-gcc
at C++11. There are some annoying problems I'm running into with avr-gcc
not providing <array>
or <initializer_list>
headers. I'm patching those with some 3rd party header files but I don't think that's the issue since I can reproduce these compilation issues on repl.it with standard C++11 and clang-6.
Aucun commentaire:
Enregistrer un commentaire