I'm recently new to using templates as a C++ feature and some of the more recent additions from C++ 11-17.
I'm trying to define a type trait for an enum class, which has some static and constant lookup tables that convert between my enum, and characters:
Enum Class:
// DNA nucleotide symbols.
enum class DNA : uint8_t {
Gap, A, C, M, G, R, S, V,
T, W, Y, H, K, D, B, N, Invalid
};
type trait:
template<typename T>
struct conversion_table {};
template<>
struct conversion_table<DNA> {
static constexpr DNA from_char[256] = {DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Gap, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::A,
DNA::B, DNA::C, DNA::D,
DNA::Invalid, DNA::Invalid, DNA::G,
DNA::H, DNA::Invalid, DNA::Invalid,
DNA::K, DNA::Invalid, DNA::M,
DNA::N, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::R, DNA::S,
DNA::T, DNA::Invalid, DNA::V,
DNA::W, DNA::Invalid, DNA::Y,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::A, DNA::B,
DNA::C, DNA::D, DNA::Invalid,
DNA::Invalid, DNA::G, DNA::H,
DNA::Invalid, DNA::Invalid, DNA::K,
DNA::Invalid, DNA::M, DNA::N,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::R, DNA::S, DNA::T,
DNA::Invalid, DNA::V, DNA::W,
DNA::Invalid, DNA::Y, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid, DNA::Invalid, DNA::Invalid,
DNA::Invalid};
static constexpr char to_char[16] = {'-', 'A', 'C', 'M', 'G', 'R', 'S', 'V', 'T', 'W',
'Y', 'H', 'K', 'D', 'B', 'N'};
};
However as far as I know static makes it defined once for all instances of the struct, and constexpr means the tables should be evaluated at compile time.
However, if I use this in a main function like so:
#import "../biosymbols.h"
int main(){
auto a = biosymbols::conversion_table<biosymbols::DNA>::from_char['A'];
return 0;
}
I get an error during compilation:
Undefined symbols for architecture x86_64:
"biosymbols::conversion_table<biosymbols::DNA>::from_char", referenced from:
_main in biosymbols_checks.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I'm not sure why though, as this is similar to examples of creating type traits on the web. Can anyone point me to what I need to be doing to fix this?
Thanks!