C++ templates and static checks ?

This problem is coming again and again to me in different formats. I try to illustrate it with following simple example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>

using namespace std;

class Vector
{
  public:
    void X()
    {
      cout<<"X in Vector\n";
    }
};


class Matrix
{
  public:
    void X(int m)
    {
      cout<<"X in Matrix\n";
    }
};


template <typename T>
int gg(T a, bool tt)
{
  if(tt)
    a.X();
  else
    a.X(21);
}

int main()
{
  Vector v;
  Matrix m;
  gg(v, true);
  gg(m, false);
}



It gives me following errors with g++:
test.cpp: In function ‘int gg(T, bool) [with T = Vector]’:
test.cpp:38: instantiated from here
test.cpp:31: error: no matching function for call to ‘Vector::X(int)’
test.cpp:8: note: candidates are: void Vector::X()
test.cpp: In function ‘int gg(T, bool) [with T = Matrix]’:
test.cpp:39: instantiated from here
test.cpp:29: error: no matching function for call to ‘Matrix::X()’
test.cpp:18: note: candidates are: void Matrix::X(int)



I understand the basic idea but on conditions it is giving error are never going to happen at runtime. How to suppress this?
Vector and Matrix must have calls that match X() and (int) because those are what you're calling.
Just make an overload for gg.

template< typename T >
void gg( T a )
{
a.X();
}

template<>
void gg<Matrix>( Matrix a )
{
a.X( 21 );
}
[/code]

int main() {
Vector v;
Matrix m
gg( v );
gg( m );
}
[/code]

(uncompiled)
One way around this is to use tag-based dispatch so that you don't have the conditional in the code. This also prevents anyone from accidentally calling the gg() function with the wrong args.
Thank for your replies. This was very simple (probably not very accurate) example while in reality some things are more complex. I cannot specialize this on first argument and also one cannot have partial specialization of functions.



One workaround that I am trying is using "compile time if" and making bool as template parameter, In my original application, this would be a good solution:
1
2
3
4
5
6
7
8
9
10
11
template <typename T, bool bb>
int gg(T a, bool tt)
{
  #if(tt)
    a.X();
  #else
    a.X(21);
  #endif
}

gg<Vector, true>(v); // Why it does not work? 



The actual application is quite complex and it's very difficult to make a good case here with short example but this solution is what is feasible in our case, if it will work?
This will not work.

Have you read anything about template metaprogramming?
A suggestion for working around your problem (this is what I use whenever I run into problems as yours):

1
2
3
4
5
6
7
8
9
template <typename T>
int ggCallXNoArgument(T a)
{ a.X();
}

template <typename T>
int ggCallXWithIntArgument(T a)
{ a.X(21);
}


Note that in this way, there is no way to get confused. In my opinion, this workaround is far superior to using the same name for inherently different functions.

Compile time template conditionals (what you want to do) are not yet implemented in C++. They are implemented in other languages however (such as language D, which is a modifaction of C++).

Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <boost/type_traits/is_same.hpp>
#include <iostream>

struct Vector
{
    void foo() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

struct Matrix
{
    void foo( int ) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

template< typename T, bool b = boost::is_same< T, Vector >::value >
struct CallFoo;

template< typename T >
struct CallFoo< T, true >
{
    void operator()( T a, int ) const
    {
        a.foo();
    }
};

template< typename T >
struct CallFoo< T, false >
{
    void operator()( T a, int x ) const
    {
        a.foo( x );
    }
};


template< typename T >
void gg( T a )
{
    CallFoo<T>()( a, 21 );
}

int main()
{
    Vector v;
    Matrix m;

    gg( v );
    gg( m );
}


This compiles and runs for me.

(The solution to the partial specialization of function templates is always to make a function object out of it).
Last edited on
Topic archived. No new replies allowed.