Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #11074 > unrolled thread

calculate number of template instantiations

Started byRuslan Mullakhmetov <tiabaldu@gmail.com>
First post2011-10-25 17:04 +0400
Last post2011-10-25 20:46 +0400
Articles 8 — 4 participants

Back to article view | Back to comp.lang.c++


Contents

  calculate number of template instantiations Ruslan Mullakhmetov <tiabaldu@gmail.com> - 2011-10-25 17:04 +0400
    Re: calculate number of template instantiations Victor Bazarov <v.bazarov@comcast.invalid> - 2011-10-25 09:32 -0400
      Re: calculate number of template instantiations Noah Roberts <roberts.noah@gmail.com> - 2011-10-25 08:30 -0700
        Re: calculate number of template instantiations Ruslan Mullakhmetov <tiabaldu@gmail.com> - 2011-10-25 20:05 +0400
        Re: calculate number of template instantiations Arne Mertz <arnemertz@googlemail.com> - 2011-10-26 02:10 -0700
      Re: calculate number of template instantiations Ruslan Mullakhmetov <tiabaldu@gmail.com> - 2011-10-25 19:42 +0400
        Re: calculate number of template instantiations Noah Roberts <roberts.noah@gmail.com> - 2011-10-25 09:43 -0700
          Re: calculate number of template instantiations Ruslan Mullakhmetov <tiabaldu@gmail.com> - 2011-10-25 20:46 +0400

#11074 — calculate number of template instantiations

FromRuslan Mullakhmetov <tiabaldu@gmail.com>
Date2011-10-25 17:04 +0400
Subjectcalculate number of template instantiations
Message-ID<j86c4d$vmq$2@speranza.aioe.org>
Hi folks,

  I got an interesting problem to play with templates. It's not 
abstract and come from real life. I'm not sure wether it has solution 
within C++, so I need advise and you opinions.

  In brief: I need to calculate number of template instantiation, 
reasoning below.

  What I need. Assume I have some template Templ<T>. In the code I 
instantiated it several times like Templ<A>, Templ<B>, ... Next I need 
to get number of instantiation _prior_ to creating any of instances of 
instantiated types. The code, I believe, clarify. Note, it's not 
compiling.

#include <iostream>

template<typename T>
struct Templ
{
	T some_dummy_value;
};

class A{};
class B{};

struct InstanceA
{
	Templ<A> inst;
	void foo(){}
};

struct InstanceB
{
	Templ<B> inst;
	void foo(){}
};


//here the question
struct Counter
{
	// ???????????
	enum
	{
		INSTANCES_NUM = // ????????
	};
}

int main()
{
	// I need this value _before_ creating any objects of
	// instantiated types.
	std::cout << Counter::INSTANCES_NUM << std::endl;

	// And only now (!) create instances of InstanceA, InstanceB
	InstanceA a; a.foo();
	InstanceB b; b.foo();
}

  As you see I need number of instantiation before creating any objects 
of instantiated types, so it's almost (at least i see so) the same as 
knowing at compile time, so i wrote

enum { INSTANCE_NUM };


  The reasoning. What I wrote above is extraction of what I need for 
simpleness and clearness. The real problem.
  I recently wrote a wrapper for plain C written simulation system (SS) 
designed with performance issues in mind, E.G. data locality. So i 
chose to use template-based approach for wrapping. This discrete 
event-driven SS managed memory itself and asks me for maximum size of 
messages _IT_ will create for me. So i wrote wrapers, but now I need to 
feed it with maximum message size of templates (==wraper for messages) 
i created.

The flow.
---------------

#include <ss.h>

struct MsgA{};
struct MsgB{};

void fill_a( MsgA * msg ){}
void fill_b( MsgB * msg ){}

// callback for SS
void event_handler( void * msg ){}

// callback for SS
void init()
{
	void * event = ss_create_event(time, recepient);
	MsgA * msg = (MsgA*) ss_message_data(event);
	fill_a( msg );
	ss_send_msg( event );
	
   // the same with msg B
	...
};

SS_AgentType agent_type = {
	&init,
	&event_handler
};

int main()
{
	agents_num = 10;
	max_msg_size = max( sizeof( MsgA ) , sizeof( MsgB ) );

	ss_init( agents_num, max_msg_size, agent_type );
	ss_run();
	// process results.
	ss_stop();
}
----------------

  I wrote wrapper that (almost) statically dispatch agents and message  
types and i avoided cast's from void *. But I still need to calculate 
message sizes. I want to avoid it to. It's quite the same as calculate 
number of instances.

BR, Ruslan Mullakhmetov

[toc] | [next] | [standalone]


#11076

FromVictor Bazarov <v.bazarov@comcast.invalid>
Date2011-10-25 09:32 -0400
Message-ID<j86dpp$jop$1@dont-email.me>
In reply to#11074
On 10/25/2011 9:04 AM, Ruslan Mullakhmetov wrote:
> I got an interesting problem to play with templates. It's not abstract
> and come from real life. I'm not sure wether it has solution within C++,
> so I need advise and you opinions.
>
> In brief: I need to calculate number of template instantiation,
> reasoning below.
>
> What I need. Assume I have some template Templ<T>. In the code I
> instantiated it several times like Templ<A>, Templ<B>, ... Next I need
> to get number of instantiation _prior_ to creating any of instances of
> instantiated types. The code, I believe, clarify. Note, it's not compiling.
> [...]

A static data member in a template would be instantiated once per every 
template instantiation and initialized once.  If that data member is of, 
say, 'int' type, you can initialize it by calling some function in which 
the counter would sit.  Pass an argument to that function to indicate 
whether to increment the counter before returning it or just return what 
it has.

It's not a problem, it sounds very much like a homework.

V
-- 
I do not respond to top-posted replies, please don't ask

[toc] | [prev] | [next] | [standalone]


#11083

FromNoah Roberts <roberts.noah@gmail.com>
Date2011-10-25 08:30 -0700
Message-ID<2ffb8a32-5fbc-475a-8f1d-b378c05d0e93@m19g2000vbm.googlegroups.com>
In reply to#11076
On Oct 25, 6:32 am, Victor Bazarov <v.baza...@comcast.invalid> wrote:
> On 10/25/2011 9:04 AM, Ruslan Mullakhmetov wrote:
>
> > I got an interesting problem to play with templates. It's not abstract
> > and come from real life. I'm not sure wether it has solution within C++,
> > so I need advise and you opinions.
>
> > In brief: I need to calculate number of template instantiation,
> > reasoning below.
>
> > What I need. Assume I have some template Templ<T>. In the code I
> > instantiated it several times like Templ<A>, Templ<B>, ... Next I need
> > to get number of instantiation _prior_ to creating any of instances of
> > instantiated types. The code, I believe, clarify. Note, it's not compiling.
> > [...]
>
> A static data member in a template would be instantiated once per every
> template instantiation and initialized once.  If that data member is of,
> say, 'int' type, you can initialize it by calling some function in which
> the counter would sit.  Pass an argument to that function to indicate
> whether to increment the counter before returning it or just return what
> it has.

This is close except that template members that are never used do not
make it into existence.  Thus unless you actually use that static
member somewhere, it never gets initialized and thus never increases
the count.  Since the goal here is to make a count variable, not an ID
or whatever, I imagine this problem is going to come up.

One way to solve this problem is to use the static variable to
initialize a non-static variable within the constructor(s) of the
object.  I don't believe you actually have to use the instance member
beyond its use in the constructor, but I actually had a use for it as
an ID.

See this SO entry:
http://stackoverflow.com/questions/4383602/how-to-force-inclusion-of-unused-object-definitions-in-a-library

[toc] | [prev] | [next] | [standalone]


#11085

FromRuslan Mullakhmetov <tiabaldu@gmail.com>
Date2011-10-25 20:05 +0400
Message-ID<j86mo7$vgr$1@speranza.aioe.org>
In reply to#11083
On 2011-10-25 19:30:24 +0400, Noah Roberts said:

> On Oct 25, 6:32 am, Victor Bazarov <v.baza...@comcast.invalid> wrote:
>> On 10/25/2011 9:04 AM, Ruslan Mullakhmetov wrote:
>> 
>>> I got an interesting problem to play with templates. It's not abstract
>>> and come from real life. I'm not sure wether it has solution within C++,
>>> so I need advise and you opinions.
>> 
>>> In brief: I need to calculate number of template instantiation,
>>> reasoning below.
>> 
>>> What I need. Assume I have some template Templ<T>. In the code I
>>> instantiated it several times like Templ<A>, Templ<B>, ... Next I need
>>> to get number of instantiation _prior_ to creating any of instances of
>>> instantiated types. The code, I believe, clarify. Note, it's not compiling.
>>> [...]
>> 
>> A static data member in a template would be instantiated once per every
>> template instantiation and initialized once.  If that data member is of,
>> say, 'int' type, you can initialize it by calling some function in which
>> the counter would sit.  Pass an argument to that function to indicate
>> whether to increment the counter before returning it or just return what
>> it has.
> 
> This is close except that template members that are never used do not
> make it into existence.  Thus unless you actually use that static
> member somewhere, it never gets initialized and thus never increases
> the count.  Since the goal here is to make a count variable, not an ID
> or whatever, I imagine this problem is going to come up.
> 
> One way to solve this problem is to use the static variable to
> initialize a non-static variable within the constructor(s) of the
> object.  I don't believe you actually have to use the instance member
> beyond its use in the constructor, but I actually had a use for it as
> an ID.
> 
> See this SO entry:
> http://stackoverflow.com/questions/4383602/how-to-force-inclusion-of-unused-object-definitions-in-a-library 
> 

Yes, I got it. I temporaly solved it by streaming value to cout. Thank 
you to. now i use useless class.

the code:

size_t counter( size_t size, bool count );
//extern size_t g_hack;


template<typename T>
class Templ
{
	class UseMe
	{
	public:
		UseMe( size_t sz )
		{
			
		}
	};	
	
	T _val;
	UseMe _useme;
public:
	
	Templ<T>(): _useme(size_counter)
	{
	}
public:
	static size_t size_counter;
};

template<typename T>
size_t Templ<T>::size_counter = counter(sizeof(T), true);

#endif
-- 
BR, Ruslan Mullakhmetov

[toc] | [prev] | [next] | [standalone]


#11091

FromArne Mertz <arnemertz@googlemail.com>
Date2011-10-26 02:10 -0700
Message-ID<a9b05650-531b-4f7c-b228-c1a8251fe345@a17g2000yqj.googlegroups.com>
In reply to#11083
> One way to solve this problem is to use the static variable to
> initialize a non-static variable within the constructor(s) of the
> object.  I don't believe you actually have to use the instance member
> beyond its use in the constructor, but I actually had a use for it as
> an ID.
>

Jut to nit-pick a bit here, this approach only counts instantiated
and
_at_least_once_constructed_ templates, because if you instantiate the
class template but never use its constructor, you get the same Problem
of the never-used-thus-never-instantiated template member. Example:

int instanceCount(bool increase = false) {
  static int ic = 0;
  if (increase) ++ic;
  return ic;
}

template <class I>
struct instCnt {
  static int unused;
  instCnt() { (void)unused; }
};

template <class I>
int instCnt<I>::unused = instanceCount(true);

#include <iostream>
using std::cout;
int main() {
  instCnt<int> ici;
  cout << sizeof(ici) << ','
       << sizeof(instCnt<double>) << ','
       << instanceCount() << '\n';
}

outputs 1,1,1 on gcc, because instCnt is only once constructed,
albeit twice instantiated.

If one wants to count all instantiations, not only the ones
actually constructed, it gets hard. I tried it by taking
the address of the static variable an passing it as template
parameter to some dummy template, that the actually inst-counted
template declares as base class in order to instantiate it,
but that seems not to instantiate the variable, either:

int instanceCount(bool increase = false) {
  static int ic = 0;
  if (increase) ++ic;
  return ic;
}

template <class I>
struct Counter
{ static const int trigger; };
template <class I>
int Counter<I>::trigger = instanceCount(true);

template <class C, const int* Ptr>
struct InstantiateCounter {};

template <class I>
struct myInstCounted : private InstantiateCounter<Counter<I>,
&Counter<I>::trigger>
{};

int main()
{
  int i = sizeof(myInstCounted<double>);
  std::cout << instanceCount() << '\n';
}

gives me a 0.

[toc] | [prev] | [next] | [standalone]


#11084

FromRuslan Mullakhmetov <tiabaldu@gmail.com>
Date2011-10-25 19:42 +0400
Message-ID<j86ldo$rgv$1@speranza.aioe.org>
In reply to#11076
On 2011-10-25 17:32:41 +0400, Victor Bazarov said:

> On 10/25/2011 9:04 AM, Ruslan Mullakhmetov wrote:
>> I got an interesting problem to play with templates. It's not abstract
>> and come from real life. I'm not sure wether it has solution within C++,
>> so I need advise and you opinions.
>> 
>> In brief: I need to calculate number of template instantiation,
>> reasoning below.
>> 
>> What I need. Assume I have some template Templ<T>. In the code I
>> instantiated it several times like Templ<A>, Templ<B>, ... Next I need
>> to get number of instantiation _prior_ to creating any of instances of
>> instantiated types. The code, I believe, clarify. Note, it's not compiling.
>> [...]
> 
> A static data member in a template would be instantiated once per every 
> template instantiation and initialized once.  If that data member is 
> of, say, 'int' type, you can initialize it by calling some function in 
> which the counter would sit.  Pass an argument to that function to 
> indicate whether to increment the counter before returning it or just 
> return what it has.
> 
> It's not a problem, it sounds very much like a homework.
> 
> V

Thanks a lot. I moved in wrong direction trying to get this info at 
compile time and stragling with fact that templates are single assigned.

There is one problem that compliler "optimize" my code and wipe out 
static member if i do not use it, say, print to stdout. i use clang. is 
it permitted by the standard? because corresponding initializing 
function is not called to! As far as i understand, c++ assume that 
function do not have a states, so it is normal to optimize in such way?

Does it dependen on number of translation units (cpp files)? I checked 
and it seems to be working. E.G. I instantiated in different cpp files 
and it shows overall information from both files. ask just in case.

the code.

// templ.h
#ifndef _TEMPL_H
#define _TEMPL_H

#include <iostream>
#include <cstdlib>

size_t counter( size_t size, bool count );

template<typename T>
class Templ
{
	T _val;
public:
	void foo()
	{
		//std::cout << "foo: " << _val.val << std::endl;
	}
	
	Templ<T>(char v)
	{
		std::cout << "Templ init " << size_counter << std::endl;
		_val.val = v;
	}
public:
	static size_t size_counter;
};

template<typename T>
size_t Templ<T>::size_counter = counter(sizeof(T), true);

#endif

// templ.c
#include <algorithm>
#include "templ.h"

size_t counter( size_t size, bool count )
{
	static size_t max_size = 0;
	
	//printf( "counter %lu\n", max_size );
	if( count )
	{
		max_size = std::max( max_size, size );
	}
	
	return max_size;
}

[toc] | [prev] | [next] | [standalone]


#11087

FromNoah Roberts <roberts.noah@gmail.com>
Date2011-10-25 09:43 -0700
Message-ID<810a04c6-9021-4e52-85b5-5a12038b41e4@y32g2000yqh.googlegroups.com>
In reply to#11084
On Oct 25, 8:42 am, Ruslan Mullakhmetov <tiaba...@gmail.com> wrote:

> There is one problem that compliler "optimize" my code and wipe out
> static member if i do not use it, say, print to stdout.

It's not an optimization.

> i use clang. is
> it permitted by the standard?

No.  It is required.

[toc] | [prev] | [next] | [standalone]


#11088

FromRuslan Mullakhmetov <tiabaldu@gmail.com>
Date2011-10-25 20:46 +0400
Message-ID<j86p58$6sf$1@speranza.aioe.org>
In reply to#11087
On 2011-10-25 20:43:44 +0400, Noah Roberts said:

> On Oct 25, 8:42 am, Ruslan Mullakhmetov <tiaba...@gmail.com> wrote:
> 
>> There is one problem that compliler "optimize" my code and wipe out
>> static member if i do not use it, say, print to stdout.
> 
> It's not an optimization.
> 
>> i use clang. is
>> it permitted by the standard?
> 
> No.  It is required.

Yes, I understood after you explanation in elsethread. Thanks.
-- 
BR, Ruslan Mullakhmetov

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web