Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Preventing multiple instantiations of a templated function

Reply
Thread Tools

Preventing multiple instantiations of a templated function

 
 
Dave Rahardja
Guest
Posts: n/a
 
      01-20-2007
Hi all,

Is it possible to prevent _at compile or link time_ the mulitple instantiation
of a templated function? In other words, if there exists a function

template <typename T> void fn();

I want to prevent the user from doing this:

int main()
{
fn<int>();
fn<double>(); // <-- should cause compile time or link time error
}

It matters that there is only one instance of the function in the entire
program. It doesn't matter which type becomes instantiated, but there cannot
be two references to the function with two different type parameters.

If this is possible, then is there a way to do this for _any_ templated
entity?

-dr
 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      01-20-2007
Dave Rahardja wrote:
> Hi all,
>
> Is it possible to prevent _at compile or link time_ the mulitple instantiation
> of a templated function? In other words, if there exists a function
>
> template <typename T> void fn();
>
> I want to prevent the user from doing this:
>
> int main()
> {
> fn<int>();
> fn<double>(); // <-- should cause compile time or link time error
> }
>
> It matters that there is only one instance of the function in the entire
> program. It doesn't matter which type becomes instantiated, but there cannot
> be two references to the function with two different type parameters.
>

Each instance of the function template is a unique function, so the
answer is probably no.

Why do you want to do this?

--
Ian Collins.
 
Reply With Quote
 
 
 
 
IR
Guest
Posts: n/a
 
      01-20-2007
Ian Collins wrote:

> Dave Rahardja wrote:
>> I want to prevent the user from doing this:
>>
>> int main()
>> {
>> fn<int>();
>> fn<double>(); // <-- should cause compile time or link time
>> error
>> }
>>
>> It matters that there is only one instance of the function in the
>> entire program. It doesn't matter which type becomes
>> instantiated, but there cannot be two references to the function
>> with two different type parameters.
>>

> Each instance of the function template is a unique function, so
> the answer is probably no.


I'd add that even if you could enforce a single *specialization* of
the template in your whole program, there are chances (depending on
the quality of your compiler) that multiples *instances* of the
specialization could be generated.


Cheers,
--
IR
 
Reply With Quote
 
Dave Rahardja
Guest
Posts: n/a
 
      01-20-2007
On Sun, 21 Jan 2007 09:14:12 +1300, Ian Collins <(E-Mail Removed)> wrote:

>Dave Rahardja wrote:
>> Hi all,
>>
>> Is it possible to prevent _at compile or link time_ the mulitple instantiation
>> of a templated function? In other words, if there exists a function
>>
>> template <typename T> void fn();
>>
>> I want to prevent the user from doing this:
>>
>> int main()
>> {
>> fn<int>();
>> fn<double>(); // <-- should cause compile time or link time error
>> }
>>
>> It matters that there is only one instance of the function in the entire
>> program. It doesn't matter which type becomes instantiated, but there cannot
>> be two references to the function with two different type parameters.
>>

>Each instance of the function template is a unique function, so the
>answer is probably no.
>
>Why do you want to do this?


I have a set of accessors in a library of this form:


template <class ReservationPolicy>
class Resource: private ReservationPolicy
{ // ...
};

template <class ReservationPolicy>
Resource& getResource()
{
static Resource<ReservationPolicy> resource;
return resource;
}


It's a simplistic Singleton accessor for a Resource that is implemented in
terms of some ReservationPolicy.

Problem is, it's an error to have the same resource accessed via a multitude
of ReservationPolicy's, because the accessor provides access to a single
underlying resource. A decision must be made at program design time as to what
ReservationPolicy that one resource is supposed to use. Once that decision is
made, it is an error to call a different instance of getResource().

I can prevent the problem at _runtime_ by:

#include <cassert>

// The resource.
template <class ReservationPolicy>
class Resource: private ReservationPolicy
{ /* ... */ };

struct ResourceTag {};

// Helper class that helps enforce a one-instantiation rule.
template <typename T>
class OneInstance
{
public:
OneInstance()
{ assert(++instanceCount == 1); }

private:
static int instanceCount;
};

template <typename T> int OneInstance<T>::instanceCount = 0;

// Accessor function. Only one instance of this function can be
// called without generating a runtime error.
template <ReservationPolicy>
Resource& getResource()
{
static OneInstance<ResourceTag> oneInstance;
static Resource<ReservationPolicy> resource;
return resource;
}

// Reservation policies
class Policy0 { /* ... */ };
class Policy1 { /* ... */ };

int main()
{
fn<Policy0>(); // OK
fn<Policy0>(); // OK
fn<Policy1>(); // Runtime assertion
}


But I'd like to know if I can prevent this problem at _compile or link_ time.

-dr
 
Reply With Quote
 
Jim Langston
Guest
Posts: n/a
 
      01-21-2007
"Dave Rahardja" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Hi all,
>
> Is it possible to prevent _at compile or link time_ the mulitple
> instantiation
> of a templated function? In other words, if there exists a function
>
> template <typename T> void fn();
>
> I want to prevent the user from doing this:
>
> int main()
> {
> fn<int>();
> fn<double>(); // <-- should cause compile time or link time error
> }
>
> It matters that there is only one instance of the function in the entire
> program. It doesn't matter which type becomes instantiated, but there
> cannot
> be two references to the function with two different type parameters.
>
> If this is possible, then is there a way to do this for _any_ templated
> entity?
>
> -dr


I can think of a way to do it using a global and a static.

#include <iostream>
#include <string>

bool fn_created = false;

template <typename T> void fn( T Val )
{
static FirstTime = true;
if ( FirstTime )
{
if ( fn_created )
throw "Function already created using diff type!";
fn_created = true;
FirstTime = false;
}
std::cout << "Value is " << Val << "\n";

}

int main()
{
fn<int>( 10 );
fn<int>( 20 );
fn<int>( 30 );
// Uncommenting out following line will cause run time throw
// fn<double>( 40.0 );

std::string wait;
std::getline( std::cin, wait );
}


 
Reply With Quote
 
Jim Langston
Guest
Posts: n/a
 
      01-21-2007
"Jim Langston" <(E-Mail Removed)> wrote in message
news:w0Bsh.540$(E-Mail Removed)...
> "Dave Rahardja" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> Hi all,
>>
>> Is it possible to prevent _at compile or link time_ the mulitple
>> instantiation
>> of a templated function? In other words, if there exists a function
>>
>> template <typename T> void fn();
>>
>> I want to prevent the user from doing this:
>>
>> int main()
>> {
>> fn<int>();
>> fn<double>(); // <-- should cause compile time or link time error
>> }
>>
>> It matters that there is only one instance of the function in the entire
>> program. It doesn't matter which type becomes instantiated, but there
>> cannot
>> be two references to the function with two different type parameters.
>>
>> If this is possible, then is there a way to do this for _any_ templated
>> entity?
>>
>> -dr

>
> I can think of a way to do it using a global and a static.
>
> #include <iostream>
> #include <string>
>
> bool fn_created = false;
>
> template <typename T> void fn( T Val )
> {
> static FirstTime = true;
> if ( FirstTime )
> {
> if ( fn_created )
> throw "Function already created using diff type!";
> fn_created = true;
> FirstTime = false;
> }
> std::cout << "Value is " << Val << "\n";
>
> }
>
> int main()
> {
> fn<int>( 10 );
> fn<int>( 20 );
> fn<int>( 30 );
> // Uncommenting out following line will cause run time throw
> // fn<double>( 40.0 );
>
> std::string wait;
> std::getline( std::cin, wait );
> }


Sorry, ignore this. This is runtime. I didn't fully understand your
question until I reread it.


 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      01-21-2007
* Dave Rahardja:
>
> Is it possible to prevent _at compile or link time_ the mulitple instantiation
> of a templated function? In other words, if there exists a function
>
> template <typename T> void fn();
>
> I want to prevent the user from doing this:
>
> int main()
> {
> fn<int>();
> fn<double>(); // <-- should cause compile time or link time error
> }
>
> It matters that there is only one instance of the function in the entire
> program. It doesn't matter which type becomes instantiated, but there cannot
> be two references to the function with two different type parameters.


With 20-20 hindsight this might seem trivial:

template< typename T >
void fn()
{
COMPILE_TIME_ASSERT( SameType<T, ::FnType>::yes );
// ...
}

where ::FnType must be defined by the client code.

It might be possible to circumvent the restriction by using an anonymous
namespace (say), but then anything can be circumvented -- I gather the
problem is to prevent inadvertent multiple specializations.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
Dave Rahardja
Guest
Posts: n/a
 
      01-21-2007
On Sun, 21 Jan 2007 04:43:46 +0100, "Alf P. Steinbach" <(E-Mail Removed)> wrote:

>* Dave Rahardja:
>>
>> Is it possible to prevent _at compile or link time_ the mulitple instantiation
>> of a templated function? In other words, if there exists a function
>>
>> template <typename T> void fn();
>>
>> I want to prevent the user from doing this:
>>
>> int main()
>> {
>> fn<int>();
>> fn<double>(); // <-- should cause compile time or link time error
>> }
>>
>> It matters that there is only one instance of the function in the entire
>> program. It doesn't matter which type becomes instantiated, but there cannot
>> be two references to the function with two different type parameters.

>
>With 20-20 hindsight this might seem trivial:
>
> template< typename T >
> void fn()
> {
> COMPILE_TIME_ASSERT( SameType<T, ::FnType>::yes );
> // ...
> }
>
>where ::FnType must be defined by the client code.
>
>It might be possible to circumvent the restriction by using an anonymous
>namespace (say), but then anything can be circumvented -- I gather the
>problem is to prevent inadvertent multiple specializations.


I don't understand how your solution works. Could you elaborate on what
SameType<...> does?
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      01-21-2007
* Dave Rahardja:
> On Sun, 21 Jan 2007 04:43:46 +0100, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
>
>> * Dave Rahardja:
>>> Is it possible to prevent _at compile or link time_ the mulitple instantiation
>>> of a templated function? In other words, if there exists a function
>>>
>>> template <typename T> void fn();
>>>
>>> I want to prevent the user from doing this:
>>>
>>> int main()
>>> {
>>> fn<int>();
>>> fn<double>(); // <-- should cause compile time or link time error
>>> }
>>>
>>> It matters that there is only one instance of the function in the entire
>>> program. It doesn't matter which type becomes instantiated, but there cannot
>>> be two references to the function with two different type parameters.

>> With 20-20 hindsight this might seem trivial:
>>
>> template< typename T >
>> void fn()
>> {
>> COMPILE_TIME_ASSERT( SameType<T, ::FnType>::yes );
>> // ...
>> }
>>
>> where ::FnType must be defined by the client code.
>>
>> It might be possible to circumvent the restriction by using an anonymous
>> namespace (say), but then anything can be circumvented -- I gather the
>> problem is to prevent inadvertent multiple specializations.

>
> I don't understand how your solution works. Could you elaborate on what
> SameType<...> does?


Checks whether the types are the same. I thought that would be clear.
But then, I'm not the world's greatest communicator...

template< typename T, typename U >
struct SameType { enum { yes = false }; };

template< typename T >
struct SameType<T, T> { enum { yes = true }; }

That leaves COMPILE_TIME_ASSERT and where ::FnType comes from.

The Boost library has a nice COMPILE_TIME_ASSERT.

::FnType must be defined by the client code.

Since it's at namespace scope (I used the global namespace for purpose
of illustration) it can't be duplicated if it's a class. And to make
more sure that it's a class you can let the function refer to a nested
typedef. The client code's definition might then look like

struct FnType { typedef double Type; };

and the function definition as

template< typename T >
void fn()
{
COMPILE_TIME_ASSERT( SameType<T, ::FnType::Type>::yes );
// ...
}

OK? Well, disclaimer: I haven't tried this. But I can't think why it
shouldn't work.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
Greg
Guest
Posts: n/a
 
      01-21-2007
Dave Rahardja wrote:
> On Sun, 21 Jan 2007 09:14:12 +1300, Ian Collins <(E-Mail Removed)> wrote:
>
> >Dave Rahardja wrote:
> >> Hi all,
> >>
> >> Is it possible to prevent _at compile or link time_ the mulitple instantiation
> >> of a templated function? In other words, if there exists a function
> >>
> >> template <typename T> void fn();
> >>
> >> I want to prevent the user from doing this:
> >>
> >> int main()
> >> {
> >> fn<int>();
> >> fn<double>(); // <-- should cause compile time or link time error
> >> }


Why not require that the client announce their choice for the
specialized type by declaring a typedef named, say, "SelectedType"? The
implementation would then specialize the function template or class
template for this typedef only (and not provide a general template
definition):

// library.h

#include "library_config.h"

template <typename T> void fn();

template <>
void fn<SelectedType>()
{
...
}

the client adds the following to library_config.h:

// library_config.h

typedef int SelectedType;

Here's the client program:

#include "library.h"

int main()
{
fn<SelectedType>(); // OK
fn<int>(); // OK
fn<double>(); // Error: undefined function
}

Note that with this technique, instantiating the "wrong" function
template leads a link time error - while instantiating the "wrong"
class template causes a compile-time error.

Greg

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Exposing certain instantiations of a templated function Bogdan C++ 1 12-04-2010 03:51 PM
Defining templated member function outside templated class chhenning C++ 5 02-13-2008 07:36 PM
templated function as parameter of another templated function Amadeus W. M. C++ 2 07-04-2006 09:59 PM
Subtypes of templated types (in templated functions) Marijn C++ 5 02-13-2004 09:50 AM
implementing a templated struct within a templated struct RA Scheltema C++ 3 01-06-2004 11:25 AM



Advertisments