
I've got a question. Is a compile-time variables concept known? It would be a set of macros that would allow assigning and changing a number assigned to a variable's name. Such variable would be considered as a constant from template argument's perspective, for example. One of the usage for such classes I have in mind would be the painless type registration of typeof macro, for example...

Is a compile-time variables concept known? It would be a set of macros
would allow assigning and changing a number assigned to a variable's name. Such variable would be considered as a constant from template argument's
"Goran Mitrovic" <gmit@inet.hr> wrote that perspective,
for example.
Is it possible that you mean something like implemented by BOOST_PP_ASSIGN_SLOT?
One of the usage for such classes I have in mind would be the painless type registration of typeof macro, for example...
I 've been using BOOST_PP_ASSIGN_SLOT for this particular purpose. Regards, Arkadiy

Arkadiy Vertleyb <vertleyb <at> hotmail.com> writes:
Is a compile-time variables concept known? It would be a set of macros
would allow assigning and changing a number assigned to a variable's name. Such variable would be considered as a constant from template argument's
"Goran Mitrovic" <gmit <at> inet.hr> wrote that perspective,
for example. Is it possible that you mean something like implemented by BOOST_PP_ASSIGN_SLOT?
No; AFAIK, you cannot update BOOST_PP_ASSIGN_SLOT from another macro (because it requires an #include directive), while __LINE__ gives you a possibility of a non-unique ID. I think I've came to a solution, but, still have to prove to myself it's good since it was done in only about 4 hours, including coming up to an idea, I cannot believe, being so simple, noone else figured it out yet (therefore I've asked that, because I have no interest in publishing something that exists any more :) ) and, finally, in more than 4 hours I was unable to merge it in your complicate typeof implementation (compilation gets very, very slow (cl.exe took more than 0.5Gb of RAM until I've removed spirit registration, for example))... :)

Goran Mitrovic wrote:
I've got a question.
Is a compile-time variables concept known?
Yes, but AFAIK it can't be done in standard C++. I guess you mean something along the lines of this hack, which takes advantage of a common compiler bug which will incorrectly find the check() and value() overloads.. Works on gcc and maybe something else, but it's not portable. template<int N> struct counter : counter<N - 1> {}; template<> struct counter<0> {}; template<int N> struct size_type { typedef char(&type)[N + 1]; }; size_type<0>::type check(...); template<class T, int N> struct set_variable { typedef counter<10> start_type; enum { current = sizeof(check((T*)0, (start_type*)0)) - 1, next = current + 1 }; friend typename size_type<next>::type check(T*, counter<next>*) {} friend typename size_type<N>::type value(T*, counter<current>*) {} }; #define CURRENT(T) (sizeof(check((T*)0, (counter<10>*)0)) - 1) #define VALUE(T) (sizeof(value((T*)0, (counter<10>*)0)) - 1) #define SET(T, N) set_variable<T, N>() #include <iostream> struct X {}; int main() { SET(X, 10); std::cout << CURRENT(X) << "\n"; std::cout << VALUE(X) << "\n"; SET(X, 15); std::cout << CURRENT(X) << "\n"; std::cout << VALUE(X) << "\n"; SET(X, 20); std::cout << CURRENT(X) << "\n"; std::cout << VALUE(X) << "\n"; } -- Daniel Wallin

Daniel Wallin <dalwan01 <at> student.umu.se> writes:
Goran Mitrovic wrote:
I've got a question.
Is a compile-time variables concept known?
Yes, but AFAIK it can't be done in standard C++. I guess you mean something along the lines of this hack, which takes advantage of a common compiler bug which will incorrectly find the check() and value() overloads.. Works on gcc and maybe something else, but it's not portable. ...
Unfortunatelly, yes - my implementation is much, much nicer, but a similar concept is used. :( However, I've just tried with latest Comeau compiler (maybe I shouldn't believe them it's 100% standard compliant), with strict compiling mode turned on - and mine implementation works there! What's the problem with overloading (one imaginable would be that compiler finds the best possible match, while the standard (maybe; I don't have it) says that a first available should be used)? Thanks and sorry if I'm boring or vastly offtopic.

Goran Mitrovic wrote:
However, I've just tried with latest Comeau compiler (maybe I shouldn't believe them it's 100% standard compliant), with strict compiling mode turned on - and mine implementation works there!
maybe you have just found defect in C++ standard or problem in Comeau compiler :) Care to send it for others to look at ? B.

Bronek Kozicki <brok <at> rubikon.pl> writes:
Goran Mitrovic wrote:
However, I've just tried with latest Comeau compiler (maybe I shouldn't believe them it's 100% standard compliant), with strict compiling mode turned on - and mine implementation works there! maybe you have just found defect in C++ standard or problem in Comeau compiler :) Care to send it for others to look at ?
I doubt, but, hey, why not after all... You can declare my compile-time variable as: declare_var_init(var1, 0) get its value by: get_var(var1) update it by: update_var(var1, 100 * get_var(var1) + 5) and make invalid by: invalid_var(var1) You may repeat last three steps in any combinations (but only at the global scope), have unimited number of variables and commands may be contained within macros... Note that by get_var() you will get a constant number, not an integer literal, so, it's unusable for preprocessor library, for example, but it can happily be used as an template argument. Comments? // Compile-time variables 1.0 by Goran Mitrovic (gmit@inet.hr) in 2004 #ifndef _compile_time_vars_h_ #define _compile_time_vars_h_ #define CTV_MAX_COUNTER_VALUE 1024 //#define CTV_MAX_COUNTER_STEP 128 #define ctv_namespace ::gmit::compile_time_vars #define ctv_namespace_internal ctv_namespace::internal namespace gmit { namespace compile_time_vars { namespace internal { typedef unsigned int uint; } #ifdef CTV_MAX_COUNTER_VALUE const ctv_namespace_internal::uint max_counter_value = CTV_MAX_COUNTER_VALUE; #else const ctv_namespace_internal::uint max_counter_value = 1024; #endif #ifdef CTV_MAX_COUNTER_STEP const ctv_namespace_internal::uint max_counter_step = CTV_MAX_COUNTER_STEP; #else const ctv_namespace_internal::uint max_counter_step = 128; #endif namespace internal { template<uint N> class size { char _size[N]; }; template<uint I> class counter : public counter<I - 1> { }; template<> class counter<0> { }; template<template<uint> class TYPE, int LAST, int STEP> class bottom_up_explicit_instantiation : private bottom_up_explicit_instantiation<TYPE, ((LAST - STEP) <= 0) ? 0 : (LAST - STEP), STEP> { TYPE<LAST> aa; }; template<template<uint> class TYPE, int STEP> class bottom_up_explicit_instantiation<TYPE, 0, STEP> { }; #ifndef CTV_NO_BOTTOM_UP_EXPLICIT_INSTANTIATION template class bottom_up_explicit_instantiation<counter, max_counter_value, max_counter_step>; #endif typedef counter<max_counter_value> *probe; } } } #define form_counter_name(name) detect_##name #define form_counter_init_name(name) init_##name #define declare_counter_init(name, value) \ namespace gmit { \ namespace compile_time_vars { \ namespace internal { \ namespace { \ size<1> form_counter_name(name) (counter<0> *); \ const int form_counter_init_name(name) = (value); \ } \ } \ } \ } #define declare_counter(name) \ declare_counter_init(name, 0) #define current_counter_unbiased(name) \ (sizeof(ctv_namespace_internal::form_counter_name(name) (ctv_namespace_internal::probe())) - 1) #define current_counter(name) \ ((int)(current_counter_unbiased(name) + ctv_namespace_internal::form_counter_init_name(name))) #define hit_counter_by(name, value) \ namespace gmit { \ namespace compile_time_vars { \ namespace internal { \ namespace { \ size<current_counter_unbiased(name) + 1 + (value)> form_counter_name(name)(counter<current_counter_unbiased(name) + (value)> *); \ } \ } \ } \ } #define hit_counter(name) \ hit_counter_by(name, 1) #define form_ctv_name(name) compile_time_var_##name #define form_ctv_counter_name(name) form_counter_name(__ctv_##name) #define update_var(name, value) \ namespace gmit { \ namespace compile_time_vars { \ namespace internal { \ namespace { \ template<> \ class form_ctv_name(name) ##<current_counter(form_ctv_counter_name(name)) + 1> { \ public: \ enum { \ my_value = (value) \ }; \ }; \ } \ } \ } \ } \ hit_counter(form_ctv_counter_name(name)) #define offset_var(name, offset) \ update_var(name, get_var(name) + offset) #define invalid_var_internal(name) \ namespace gmit { \ namespace compile_time_vars { \ namespace internal { \ namespace { \ template<> \ class form_ctv_name(name) ##<current_counter(form_ctv_counter_name(name))> { \ }; \ } \ } \ } \ } #define invalid_var(name) \ hit_counter(form_ctv_counter_name(name)) \ invalid_var_internal(name) #define get_var(name) \ ((int)(ctv_namespace_internal::form_ctv_name(name)##<current_counter (form_ctv_counter_name(name))>::my_value)) #define declare_var(name) \ declare_counter(form_ctv_counter_name(name)) \ namespace gmit { \ namespace compile_time_vars { \ namespace internal { \ namespace { \ template<int ID> \ class form_ctv_name(name) { \ }; \ } \ } \ } \ } #define declare_var_init(name, value) \ declare_var(name) \ update_var(name, value) #endif // !_compile_time_vars_h_

On Tue, 24 Aug 2004 22:10:22 +0200, Daniel Wallin <dalwan01@student.umu.se> wrote:
Goran Mitrovic wrote:
I've got a question.
Is a compile-time variables concept known?
Yes, but AFAIK it can't be done in standard C++. I guess you mean something along the lines of this hack, which takes advantage of a common compiler bug which will incorrectly find the check() and value() overloads.. Works on gcc and maybe something else, but it's not portable.
template<int N> struct counter : counter<N - 1> {}; template<> struct counter<0> {};
template<int N> struct size_type { typedef char(&type)[N + 1]; };
size_type<0>::type check(...);
template<class T, int N> struct set_variable { typedef counter<10> start_type;
enum { current = sizeof(check((T*)0, (start_type*)0)) - 1, next = current + 1 };
friend typename size_type<next>::type check(T*, counter<next>*) {} friend typename size_type<N>::type value(T*, counter<current>*) {} };
#define CURRENT(T) (sizeof(check((T*)0, (counter<10>*)0)) - 1) #define VALUE(T) (sizeof(value((T*)0, (counter<10>*)0)) - 1) #define SET(T, N) set_variable<T, N>()
#include <iostream>
struct X {};
int main() { SET(X, 10); std::cout << CURRENT(X) << "\n"; std::cout << VALUE(X) << "\n";
SET(X, 15); std::cout << CURRENT(X) << "\n"; std::cout << VALUE(X) << "\n";
SET(X, 20); std::cout << CURRENT(X) << "\n"; std::cout << VALUE(X) << "\n"; }
-- Daniel Wallin
Just a suggestion: Making set_variable a parameter to the check and value functions should make them available for standard compliant compilers as well, if I have interpreted the standards correctly. ... template<class T,int Current, int N> struct set_variable { typedef counter<10> start_type; set_variable(int); set_variable() {} enum { current = Current, next = current + 1 }; friend typename size_type<next>::type check(set_variable<T,Current,N> const&,T*, counter<next>*) {} friend typename size_type<N>::type value(set_variable<T,Current,N> const&,T*, counter<current>*) {} }; #define CURRENT(T) (sizeof(check(1,(T*)0, (counter<10>*)0)) - 1) #define VALUE(T) (sizeof(value(1,(T*)0, (counter<10>*)0)) - 1) #define SET(T, N) set_variable<T,CURRENT(T), N>() ... This compiles fine for VC 6.5 (so does the original example, so this is no proof of compliancy)
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Peder Holt wrote:
This compiles fine for VC 6.5 (so does the original example, so this is no proof of compliancy)
Unfortunately, it doesn't work on intel linux v8 in strict mode. As far as I can tell, you can't use friend functions of templates in this manner at all. In normal mode it works fine. Also, you can't use large levels of recursion, the maximum is about 64, so your start type is limited to counter<64>, or something similar. But it's probably possible to use two counters. I imagine this is probably similar on all EDG based compilers. Daniel
participants (6)
-
Arkadiy Vertleyb
-
Bronek Kozicki
-
Daniel James
-
Daniel Wallin
-
Goran Mitrovic
-
Peder Holt