0

I've got the following sample code and would like to get some help to understand why I am unable to compile it using clang and g++ on Linux?

#include <iostream>

using namespace std;

typedef enum COLORS {
    RED = 0,
    GREEN,
    BLUE,
    ORANGE,
    MAROON,
    WHITE,
    BLACK
} COLORS;

template <COLORS C> void whatColor( COLORS x ) {
    cout << "this can be any color!!!" << endl;
}

template<> void whatColor<RED>( COLORS x ) {
    cout << "this is RED!!!" << endl;
}

template<> void whatColor<GREEN>( COLORS x ) {
    cout << "this is GREEN!!!" << endl;
}

template<> void whatColor<BLUE>( COLORS x ) {
    cout << "this is BLUE!!!" << endl;
}

template<> void whatColor<ORANGE>( COLORS x ) {
    cout << "this is ORANGE!!!" << endl; 
}

int main( ) {
    const COLORS red=RED;

    whatColor( red );
    whatColor<RED>( RED );
    whatColor<red>( red );
    whatColor<RED>( red );
}

The failure I am seeing is this:

CXX [misc]  tmpl.cpp
src/tmpl.cpp:40:2: error: no matching function for call to 'whatColor'
    whatColor( red );
    ^~~~~~~~~
src/tmpl.cpp:15:26: note: candidate template ignored: couldn't infer template argument 'C'
template <COLORS C> void whatColor( COLORS x ) {
                     ^
1 error generated.
make: *** [obj/tmpl.o] Error 1

It is unclear to me why it cannot infer the argument type in this case

TheBadCat
  • 19
  • 1
  • 6

1 Answers1

0

with the code:

template <COLORS C> void whatColor( COLORS x ){...}

you define a template function, templated on the value C of type Color, this function also coincidentally happens to take a Color x as a parameter (which isn't actually used)

You also then specialise that function for some possible values of C.

when you call

whatColor( red );

You are providing a value for Color x but not a value for C. Since the X and C are not related (even though they happen to both be colors) there's no way for the complier to decide what value of C to use.

you should decide whether you want the color to be dynamically or statically typed (is it fixed at compile time or not) at the moment your code attempts a mix of both

for example it would currently be possible to call it like this

whatColor<RED>( BLUE );

which is a bit odd really. C = RED, X = BLUE (but X is ignored)

if you want to fix the color at compile time you could remove the X function parameter and just use the C template parameter

template <COLORS C> void whatColor() //definition
whatColor<RED>(); // call

or if you want the function to use the X parameter, then don't use a template

void whatColor(COLORS X)
{
    // maybe use a switch statement on X
}

if the different colours were different types rather than values then overloading or template code would work ( not that I'm recommending either for this)

class Red{};
class Blue{};
template <typename COLORSTYPE> void whatColor( COLORSTYPE x )
{ 
   // ...
}

// or overloads

void whatColor(Red dummy){//...}
void whatColor(Blue dummy){//...}

Red red;
whatColor(red);
ROX
  • 1,256
  • 8
  • 18
  • Hi @ROX, I've removed the input parameter to the function and that works fine if the template parameter is a COLORS constant. However, I also need it to be able to take a COLORS variable: `COLORS red=RED; whatColor( );` If I make red a const the compiler seems to be smart enough to deduce the type and it works. However, if it is not a const it will not even compile. Giving this error: src/tmpl.cpp:41:2: error: no matching function for call to 'whatColor' whatColor( ); src/tmpl.cpp:15:26: note: candidate template ignored: invalid explicitly-specified... – TheBadCat Nov 10 '16 at 02:06
  • C++ templates require types or values that are fixed at compile time. If you want to use a runtime variable then you cannot use it as a template parameter. (if you really want to use templates to handle each colour you could do that inside the switch statement example above). I think your error message now is because its trying to match the template parameter by type which is fixed as Colors,not by value which isn't fixed. – ROX Nov 10 '16 at 12:03