c++ - refer to global data from a template function? -


templates inline - have supply definition declaration.

global (static) data requires there 1 definition of data (but can declared multiple times).

so, class static data, 1 declares static in class definition (header), , storage static in implementation file (.cpp).

but 1 template needs refer static / global data?

here's bit of code give concrete consider:

        // represent in formal manner can encoded in msvs format specification         // format specification, consists of optional , required fields, has following form:         // %[flags][width][.precision][{h | l | ll | w | | i32 | i64}] type         // based on https://msdn.microsoft.com/en-us/library/56e442dc.aspx         struct formatspec         {             enum size {                 normal,                 h,                 l,                 ll,                 w,                 i,                 i32,                 i64             };              enum type {                 invalid,                 character,                 signed_integer,                 unsigned_integer,                 unsigned_octal,                 unsigned_hex,                 floating_point,                 expontential_floating_point,                 engineering_floating_point,                 hex_double_floating_point,                 pointer,                 string,                 z_string             };              unsigned    fleftalign : 1;             unsigned    falwayssigned : 1;             unsigned    fleadingzeros : 1;             unsigned    fblankpadding : 1;             unsigned    fbaseprefix : 1;              unsigned    width;             unsigned    precision;              size        size_;             type        type_;         };          struct formatspectypedatum         {             formatspec::type    id;         // id             const tchar *       symbol;     // text symbol         };          formatspectypedatum ktypespecs[] =         {             { formatspec::character, _t("c") },             { formatspec::character, _t("c") },             { formatspec::signed_integer, _t("d") },             { formatspec::signed_integer, _t("i") },             { formatspec::unsigned_octal, _t("o") },             { formatspec::unsigned_integer, _t("u") },             { formatspec::unsigned_hex, _t("x") },             { formatspec::unsigned_hex, _t("x") },             { formatspec::expontential_floating_point, _t("e") },             { formatspec::expontential_floating_point, _t("e") },             { formatspec::floating_point, _t("f") },             { formatspec::floating_point, _t("f") },             { formatspec::engineering_floating_point, _t("g") },             { formatspec::engineering_floating_point, _t("g") },             { formatspec::hex_double_floating_point, _t("a") },             { formatspec::hex_double_floating_point, _t("a") },             { formatspec::pointer, _t("p") },             { formatspec::string, _t("s") },             { formatspec::string, _t("s") },             { formatspec::z_string, _t("z") },         };          template <typename ctype>         bool decodeformatspectype(const ctype * & format, formatspec & spec)         {             (unsigned = 0; < countof(ktypespecs); ++i)                 if (format[0] == ktypespecs[i].symbol[0])                 {                     spec.type_ = ktypespecs[i].id;                     ++format;                     return true;                 }             return false;         } 

it's relatively simple - symbolic id character representation lookup table.

i want able use decodeformatspectype<>() char, unsigned char, wchar_t, etc.

i remove template decodeformatspectype() , supply overloaded interfaces various character types.

the main thing data isn't changing - unsigned char 'c' , wchar_t 'c' , legacy char 'c' have exact same value, regardless of character's storage size (for core ascii characters true, although there undoubtedly other encodings such edbic isn't true, that's not problem i'm attempting solve here).

i want understand "how construct c++ libraries can access global data defined in 1 location - stored array - , want accessing templated code know length of global data, can normal non-templated code have global symbol table i've shown in example code having table , implementation needs size both exist in appropriate .cpp file"

does make sense?

global data + functions need know exact definition can presented (with interface) generic (to valid domain).

a function template can use global functions , global data without problem.

if want encapsulate definition of ktypespecs , not have defined in header file, can use couple of functions provide access data.

size_t getnumberoftypespecs();  // provide read access data. formatspectypedatum const* gettypespecs(); 

and implement decodeformatspectype as

template <typename ctype> bool decodeformatspectype(const ctype * & format, formatspec & spec) {    size_t num = getnumberoftypespecs();    formatspectypedatum const* typespecs = gettypespecs();     (unsigned = 0; < num; ++i)       if (format[0] == typespecs[i].symbol[0])       {          spec.type_ = typespecs[i].id;          ++format;          return true;       }    return false; } 

the functions getnumberoftypespecs , gettypespecs can implemented in .cpp file as:

// make data file scoped global variable. static formatspectypedatum ktypespecs[] = {    { formatspec::character, _t("c") },    { formatspec::character, _t("c") },    { formatspec::signed_integer, _t("d") },    { formatspec::signed_integer, _t("i") },    { formatspec::unsigned_octal, _t("o") },    { formatspec::unsigned_integer, _t("u") },    { formatspec::unsigned_hex, _t("x") },    { formatspec::unsigned_hex, _t("x") },    { formatspec::expontential_floating_point, _t("e") },    { formatspec::expontential_floating_point, _t("e") },    { formatspec::floating_point, _t("f") },    { formatspec::floating_point, _t("f") },    { formatspec::engineering_floating_point, _t("g") },    { formatspec::engineering_floating_point, _t("g") },    { formatspec::hex_double_floating_point, _t("a") },    { formatspec::hex_double_floating_point, _t("a") },    { formatspec::pointer, _t("p") },    { formatspec::string, _t("s") },    { formatspec::string, _t("s") },    { formatspec::z_string, _t("z") }, };  size_t getnumberoftypespecs() {    return sizeof(ktypespecs)/sizeof(ktypespecs[0]); }  formatspectypedatum const* gettypespecs() {    return ktypespecs; } 

update, in response comment op

yes, can. following valid:

size_t getnumberoftypespecs() {    static constexpr size_t num = sizeof(ktypespecs)/sizeof(ktypespecs[0]);    return num; }  constexpr size_t getnumberoftypespecs() {    return sizeof(ktypespecs)/sizeof(ktypespecs[0]); } 

Comments