Fwd: [OT] [metaprogramming] Importance of order of delarations/definitions.

Hi! Could anyone tell me if there is any example where in e.g. metaprogramming there is a need of strict order of declarations and definitions of templates? Theoretically there should not be a problem, but maybe there are some tricks where order influence on fitting types and/or for lookup of specializations. Generally the question is related to the fact, that GCC force user to put typedefs and declaration/definitions in proper order before any usage of types. And I am looking for the example which points why we can NOT mix all - when the order is important. Regards. -- |\/\/| Seweryn Habdank-Wojewódzki \/\/

on Thu Jun 21 2007, Seweryn Habdank-Wojewódzki <shw-AT-agh.edu.pl> wrote:
Hi!
Could anyone tell me if there is any example where in e.g. metaprogramming there is a need of strict order of declarations and definitions of templates?
Theoretically there should not be a problem, but maybe there are some tricks where order influence on fitting types and/or for lookup of specializations.
Generally the question is related to the fact, that GCC force user to put typedefs and declaration/definitions in proper order before any usage of types. And I am looking for the example which points why we can NOT mix all - when the order is important.
I'm sorry, I can't understand what you're saying. Examples might help. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

Hi! Thanks for reply. # piątek 22 czerwca 2007 06:18, @ David Abrahams:
I'm sorry, I can't understand what you're saying. Examples might help.
I try :-). Let's consider such a hiphotetical situation. We have a classes: template < typename T > struct Bar { T t_; } class Foo { public: typedef int A; typedef Bar<A> BA; // ... }; Above order of definitions is important, due to language demand and compiler functionality, But ... let's make a hypothesis, that compiler can make a map of "symbols" in one translation unit, and sort topologically symbols. So without any _loss_ of functionality, we can write: class Foo { public: // ... typedef Bar<A> BA; typedef int A; }; template < typename T > struct Bar { T t_; } The hypothetical compiler can make a map, that will mark which symbol is known and what is just used by the programmer. So let's try to analyse such a recognition of symbols process. The first step is topological sorting of the graph of the dependencies of symbols. The second step we can go through compilation normally. But topological sorting can change something in the code what is reached, by that typical assumption that definitions and declarations are in proper order. So I am looking for the example where e.g. topological sorting of symbols can destroy functionality. The example above is no that case. Below is an example where sequence _is_ important: typedef int A; namespace B { struct C { A a; }; typedef double A; struct D { A a; }; } But this code is an example of the bad design. So am looking the code where design is good, and any sorting of symbols will change functionality. Regards. -- |\/\/| Seweryn Habdank-Wojewódzki \/\/

Seweryn Habdank-Wojewódzki said: (by the date of Fri, 22 Jun 2007 09:43:00 +0200) wouldn't it help if you just add a template declaration beforehand? template < typename T > struct Bar; or sth like that.
class Foo { public: // ... typedef Bar<A> BA; typedef int A; };
template < typename T > struct Bar { T t_; };
-- Janek Kozicki |

Hi!
wouldn't it help if you just add a template declaration beforehand?
template < typename T > struct Bar;
or sth like that.
Of course it helps, but this is not the point. Maybe other explanation. Let's observe the class: class Foo { public: void foo() { a = 100; } private: int a; }; Above there is no problem for the compiler to see field "a", even if it is below first usage. This code is equivalent to: class Foo { private: int a; public: void foo() { a = 100; } }; Compiler by default makes such a "sorting". If you do the same with typedef you will fail, due to standard demand and compilers implementation. But, I am looking if this demand is really strong. So I am looking for a implementation (the code) where really e.g. sequence of typedefs or other things will have an influence on the compilation process, not only by forcing by standard or compiler :-). This is the point why I am looking on metaprograms, because, there are some important stuff regarding to the solving values of sizeof(), or where the sequence of typedefs can influence on analysis (identyfication) of the type. Such a "tricky" code can change resolution like in STD item 6.8 Ambiguity resolution [stmt.ambig] or 8.2 Ambiguity resolution [dcl.ambig.res]. If such a code do not exists there is e question why typedef have to be placed in proper order. Regards. -- |\/\/| Seweryn Habdank-Wojewódzki \/\/

On 6/22/07, Seweryn Habdank-Wojewódzki <shw@agh.edu.pl> wrote:
Let's observe the class:
class Foo { public: void foo() { a = 100; } private: int a; };
Above there is no problem for the compiler to see field "a", even if it is below first usage. This code is equivalent to:
class Foo { private: int a; public: void foo() { a = 100; } };
I think I see your confusion. The members declared in the class are visible in the inline function's body. Maybe you should think of it like this. class Foo { public: void foo(); private: int a; }; inline void Foo::foo() { a = 100; } ... is equivalent to ... class Foo { private: int a; public: void foo(); }; inline void Foo::foo() { a = 100; } But like Stefan said the important thing is that declarations are visible at (occur prior to) the call sites be they types, objects, or functions. So the following two errors are due to declarations of 'a' not being visible ... struct foo { typedef a b; // error }; struct bar { static const int b = a; // error }; The following doesn't help ... struct foo { typedef a b; // error typedef int a; }; struct bar { static const int b = a; // error static const int a = 0; }; But the following does ... struct foo { typedef int a; typedef a b; }; struct bar { static const int a = 0; static const int b = a; }; Daniel

Seweryn Habdank-Wojewódzki wrote:
Hi!
Thanks for reply.
# piątek 22 czerwca 2007 06:18, @ David Abrahams:
I'm sorry, I can't understand what you're saying. Examples might help.
I try :-).
Let's consider such a hiphotetical situation. We have a classes:
template < typename T > struct Bar { T t_; }
class Foo { public: typedef int A; typedef Bar<A> BA; // ... };
Above order of definitions is important, due to language demand and compiler functionality
I don't think this statement is accurate. What is important is not the order of definitions, but the visibility of declarations at any particular place in the code where a particular symbol is actually used (the 'call site'). There are clear rules about how ambiguities are to be resolved in binding names to declared types or variables. They have nothing to do with in what order the declarations appeared (and are seen by the compiler). Regards, Stefan -- ...ich hab' noch einen Koffer in Berlin...

Hi!
Let's consider such a hiphotetical situation. We have a classes:
[...]
Above order of definitions is important, due to language demand and compiler functionality
I don't think this statement is accurate. What is important is not the order of definitions, but the visibility of declarations at any particular place in the code where a particular symbol is actually used (the 'call site').
There are clear rules about how ambiguities are to be resolved in binding names to declared types or variables. They have nothing to do with in what order the declarations appeared (and are seen by the compiler).
YES! You are right, this is the point, and I am looking for the example where this aspects are highlighted. Regards. -- |\/\/| Seweryn Habdank-Wojewódzki \/\/

On 22/06/07, Seweryn Habdank-Wojewódzki <shw@agh.edu.pl> wrote:
So I am looking for the example where e.g. topological sorting of symbols can destroy functionality. The example above is no that case.
But this code is an example of the bad design. So am looking the code where design is good, and any sorting of symbols will change functionality.
What about using a template class with a partial specialization that is defined afterwards? template <class A> class T { A a; }; int func() { return sizeof(T<void *>); } template <class A> class T<A *> { A *a[10]; }; I think that all uses that change the meaning of any symbol after it's defined is bad design or bad implementation. If you were to change the ordering inherently, you'd have to give very explicit warnings or errors on these kinds of situations (in particular, typedefs and partial specializations). Regards, Peter

Hi Peter Peter Bindels wrote:
On 22/06/07, Seweryn Habdank-Wojewódzki <shw@agh.edu.pl> wrote: What about using a template class with a partial specialization that is defined afterwards?
Seems to be good idea.
template <class A> class T { A a; };
int func() { return sizeof(T<void *>); }
template <class A> class T<A *> { A *a[10]; };
I think that all uses that change the meaning of any symbol after it's defined is bad design or bad implementation. If you were to change the ordering inherently, you'd have to give very explicit warnings or errors on these kinds of situations (in particular, typedefs and partial specializations).
Yes, this example is really good. Thanks a lot for it. Best regards. -- |\/\/| Seweryn Habdank-Wojewódzki \/\/

Hi again I am little change this example and it contains interesting functionality: #include <iostream> template <class A> class T { A a; }; class is_original_version_of_template { public: static bool const value; }; bool const is_original_version_of_template::value (sizeof(T<void *>) == sizeof(T<void *>)); template <class A> class T<A *> { A *a[10]; }; class is_not_original_version_of_template // specialized version { public: static bool const value; }; bool const is_not_original_version_of_template::value (sizeof(T<void *>) == is_original_version_of_template::value); int main() { std::cout << "is_original_version_of_template " << is_original_version_of_template::value << '\n'; std::cout << "is_not_original_version_of_template " << is_not_original_version_of_template::value << '\n'; } Regards. -- |\/\/| Seweryn Habdank-Wojewódzki \/\/

Seweryn Habdank-Wojewódzki wrote:
Hi again
I am little change this example and it contains interesting functionality:
This has nothing to do with boost. Can you please take this discussion to a more appropriate forum ? Thanks, Stefan -- ...ich hab' noch einen Koffer in Berlin...

Hi
I am little change this example and it contains interesting functionality:
This has nothing to do with boost. Can you please take this discussion to a more appropriate forum ?
I am really sorry if I am disturbing you. I will stop. Best regards. -- |\/\/| Seweryn Habdank-Wojewódzki \/\/

On 6/23/07, Seweryn Habdank-Wojewódzki <shw@agh.edu.pl> wrote:
Hi
I am little change this example and it contains interesting functionality:
This has nothing to do with boost. Can you please take this discussion to a more appropriate forum ?
I am really sorry if I am disturbing you. I will stop.
It's just that if the issue doesn't have to do with boost, it's a little off topic for this list. Usenet comp.lang.c++ might be a better venue for whatever it is that you're trying to get at. Daniel
participants (6)
-
Daniel Walker
-
David Abrahams
-
Janek Kozicki
-
Peter Bindels
-
Seweryn Habdank-Wojewódzki
-
Stefan Seefeld