I'm trying to represent some meta information in a structured way (i.e. using a class). It's header-only and I need to support c++11 so can't use inline variables. I've come up with a couple of potential solutions but each has its drawbacks. Any suggestions would be much appreciated.
Solution A - working but templated ID
Simplified code example:
library.h:
template <typename Container, int ID>
class FieldInfo {
public:
static constexpr int id = ID;
};
sth.h:
struct Sth {/* contains fieldA and fieldB - just as an example */};
// SthInfo holds meta-information about fields in Sth
struct SthInfo {
static constexpr FieldInfo<Sth, 1> fieldA{};
static constexpr FieldInfo<Sth, 2> fieldB{};
};
SthInfo::fieldA
is then used as an argument to a templated Processor<Type>::work(field)
which :
- checks that the "container type" matches this processor
- and uses the ID together with other non-relevant args do some internal logic
library.h:
template <typename T>
class Processor {
public:
template <typename Container, int ID>
someReturnType work(FieldInfo<Container, ID> field, someMoreArgs) {
static_assert(std::is_same<Container, T>::value, "Given field can't be processed - container type mismatch");
// some business logic using the ID, i.e. accessing `field.id`
}
};
app.cpp:
#include "library.h"
#include "sth.h"
// and called like this
int main() {
Processor<Sth> processor;
processor.work(SthInfo::fieldA);
}
This works (compiles and links) fine on Linux and Windows. However, Is there a way to avoid the ID
constant in the template and have it as a field in the FieldInfo
class? Any other improvement ideas?
Broken solution B - won't link
I've tried changing to the following code but it doesn't link on Linux (but does on Windows...) with undefined reference to SthInfo::fieldA
:
library.h:
template <typename Container>
class FieldInfo {
public:
const int id;
};
sth.h:
struct Sth {/* contains fieldA and fieldB - just as an example */}
// SthInfo holds meta-information about fields in Sth
struct SthInfo {
static constexpr FieldInfo<Sth> fieldA{1};
static constexpr FieldInfo<Sth> fieldB{2};
}
main.cpp - same as with "Solution A".
Solution C - constexpr function - not so nice to use.
changing SthInfo::fieldA
to a constexpr function helps but then you have to use ()
when using in the app code...
library.h - same as solution B
sth.h:
struct Sth {/* contains fieldA and fieldB - just as an example */};
// SthInfo holds meta-information about fields in Sth
struct SthInfo {
static constexpr FieldInfo<Sth> fieldA() { return FieldInfo<Sth>{1}; }
static constexpr FieldInfo<Sth> fieldB() { return FieldInfo<Sth>{2}; }
};
app.cpp:
int main() {
Processor<Sth> processor;
processor.work(SthInfo::fieldA()); // note fieldA() function call
}
Aucun commentaire:
Enregistrer un commentaire