By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,200 Members | 1,754 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,200 IT Pros & Developers. It's quick & easy.

Preventing multiple instantiations of a templated function

P: n/a
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 Tvoid 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
Jan 20 '07 #1
Share this Question
Share on Google+
14 Replies


P: n/a
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 Tvoid 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.
Jan 20 '07 #2

P: n/a
IR
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
Jan 20 '07 #3

P: n/a
On Sun, 21 Jan 2007 09:14:12 +1300, Ian Collins <ia******@hotmail.comwrote:
>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 Tvoid 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<ReservationPolicyresource;
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 Tint 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<ResourceTagoneInstance;
static Resource<ReservationPolicyresource;
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
Jan 20 '07 #4

P: n/a
"Dave Rahardja" <as*@me.comwrote in message
news:s2********************************@4ax.com...
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 Tvoid 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 Tvoid 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 );
}
Jan 21 '07 #5

P: n/a
"Jim Langston" <ta*******@rocketmail.comwrote in message
news:w0**************@newsfe05.lga...
"Dave Rahardja" <as*@me.comwrote in message
news:s2********************************@4ax.com...
>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 Tvoid 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 Tvoid 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.
Jan 21 '07 #6

P: n/a
* 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 Tvoid 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?
Jan 21 '07 #7

P: n/a
On Sun, 21 Jan 2007 04:43:46 +0100, "Alf P. Steinbach" <al***@start.nowrote:
>* 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 Tvoid 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?
Jan 21 '07 #8

P: n/a
* Dave Rahardja:
On Sun, 21 Jan 2007 04:43:46 +0100, "Alf P. Steinbach" <al***@start.nowrote:
>* 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 Tvoid 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?
Jan 21 '07 #9

P: n/a
Dave Rahardja wrote:
On Sun, 21 Jan 2007 09:14:12 +1300, Ian Collins <ia******@hotmail.comwrote:
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 Tvoid 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 Tvoid 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

Jan 21 '07 #10

P: n/a
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 Tvoid fn();

I want to prevent the user from doing this:

int main()
{
fn<int>();
fn<double>(); // <-- should cause compile time or link time error
}
You could set up a script to parse the linker output and see if
the function has been instantiated twice. This is system-specific
of course :)

Jan 21 '07 #11

P: n/a
Old Wolf 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 Tvoid fn();

I want to prevent the user from doing this:

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

You could set up a script to parse the linker output and see if
the function has been instantiated twice. This is system-specific
of course :)
It might also be possible to schedule twice-monthly, on-site code
inspections of each client installation that uses this function
template - as yet another way to provide an extra margin of safety.
After all, it's hard to top in situ verfication by the very same
engineer or engineers who wrote the library - to determine for sure
whether the client has properly met all of its requirements. Effective?
surely, but practical? not hardly.

In the real world, a well-designed software interface should enforce
its own requirements (and report - with at least a semi-coherent
explanation - when any of its requirements have not been met). A
poorly-designed software interface, in constrast, is often one designed
to suit the convenience and tastes of its implementor. As such, this
kind of interface usually requires the client to absorb a set of
"just-so" knowledge describing the proper use of the software - a set
of requirements that often seem to follow no known existing convention
or practice, be motivated by no discernable rationale or purpose, yet
nonetheless will fail - even silently - unless its inscrutable
requirements and procedures are followed to a tee.

So, if at anytime, it starts to look that a particular software
interface under design is looking more and more like it belongs in the
latter category instead of the former, then a top-design review of the
entire interface is probably in order.

Greg

Jan 22 '07 #12

P: n/a
>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.
I see. However this pushes the responsibility for creating the check type
(FnType) to the user of the library, where she has to ensure that every
instantiation of fn() will see the _same_ FnType. Putting something in the
global namespace is also undesirable for my library design. I've been burned
too many times by symbol clashes when two libraries collide.

-dr
Jan 22 '07 #13

P: n/a
On 21 Jan 2007 14:47:58 -0800, "Old Wolf" <ol*****@inspire.net.nzwrote:
>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 Tvoid fn();

I want to prevent the user from doing this:

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

You could set up a script to parse the linker output and see if
the function has been instantiated twice. This is system-specific
of course :)
This is the very situation that I'm trying to prevent: a manual,
build-specific, or team process-based solution. I'm building a generic library
that must work on a wide variety of compilers and target microprocessors, and
I want semantic checks to be as automatic as possible, using standard C++ as
much as possible.

-dr
Jan 22 '07 #14

P: n/a
* Dave Rahardja:
>>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.

I see. However this pushes the responsibility for creating the check type
(FnType) to the user of the library,
Yes of course. It's the user that uses the template and decides the
template argument, no? Only the user knows that type.

where she has to ensure that every
instantiation of fn() will see the _same_ FnType.
Yes, that's ensured by the one-definition-rule (ODR), paragraph
something of the standard.

Putting something in the
global namespace is also undesirable for my library design. I've been burned
too many times by symbol clashes when two libraries collide.
The use a namespace specific to your library. In C++ namespaces can be
extended.

--
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?
Jan 22 '07 #15

This discussion thread is closed

Replies have been disabled for this discussion.