help-gplusplus
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Explicite Template Instantiation and Inline


From: Paul Pluzhnikov
Subject: Re: Explicite Template Instantiation and Inline
Date: Sat, 19 May 2007 15:36:14 -0700
User-agent: Gnus/5.1006 (Gnus v5.10.6) XEmacs/21.4 (Jumbo Shrimp, linux)

tthunder@gmx.de writes:

> Can anybody think about another possibility?

Ok, I think your requirements are:

- compile-time error if modulo<bool>(bool, bool) is ever called.
- foo<bool> explicitly instantiated (because it must be exported).
- foo<T>::operator=(const T&) calls modulo<T>(T, T)

The "standard" answer is to use type traits.

Here is an "example" solution (works with g++ 3.3.3 and 4.2.0,
you'll have to check whether it works with VC71 yourself).

$ cat foo.h
template <bool X> void compile_time_assert()
{
  char buf[X ? 2 : 0]; // fails to compile if X==false
  return;
}

template <typename T> struct type_traits {
  static const bool is_bool = false;
};

template <> struct type_traits<bool> {
  static const bool is_bool = true;
};

template <typename T> T modulo(T a, T b)
{
  compile_time_assert< type_traits<T>::is_bool == false>();
  // the rest of modulo computation
  return a % b;
}

template <typename T> struct foo {
    inline foo<T>& operator=(const T&);
    T other();
    T another();
  private:
    T m_x;
};

template <typename T> T foo<T>::other() { }
template <typename T> T foo<T>::another() { }
// other non-inline foo<T>:: methods go here ...

#ifdef INSTANTIATE_FOO

template struct foo<bool>;
template struct foo<int>;
template struct foo<long>;

#else

template <typename T>
foo<T>& foo<T>::operator=(const T& x) 
{ 
  m_x = modulo<T>(m_x, x); 
  return *this;
}

// other inline foo<T>:: methods go here ...
#endif

$ cat main.cpp
#define INSTANTIATE_FOO
#include "foo.h"

int main() { return 0; }

This compiles and links just fine, and provides non-inlined instances:

$ g++ -c main.cpp && nm -C main.o && g++ main.o && echo ok
00000000 T main
00000000 W foo<bool>::other()
00000000 W foo<bool>::another()
00000000 W foo<int>::other()
00000000 W foo<int>::another()
00000000 W foo<long>::other()
00000000 W foo<long>::another()
ok

Now let's what the "client" code that actually uses foo<T>
looks like.

$ cat client.cpp
#include "foo.h"

void fn1()
{
  foo<int> f;
  f = 1;
}

#ifdef BUG
void fn2()
{
  foo<bool> f;
  f = true;
}
#endif

$ g++ -c client.cpp && nm -C client.o
00000000 W void compile_time_assert<true>()
00000000 T fn1()
00000000 W int modulo<int>(int, int)
00000000 W foo<int>::operator=(int const&)

Good so far: it compiled; it defined (weak) inline functions.

Now let's see what happens if the client tries to use "prohibited"
interface:

$ g++ -c client.cpp -DBUG
foo.h: In function `void compile_time_assert() [with bool X = false]':
foo.h:17:   instantiated from `T modulo(T, T) [with T = bool]'
foo.h:46:   instantiated from `foo<T>& foo<T>::operator=(const T&) [with T = 
bool]'
client.cpp:13:   instantiated from here
foo.h:3: error: creating array with size zero (`0')

Cheers,
-- 
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]