Pergunta

I have the following bit of code which has two versions of the function foo. I'd like if a variable is passed for the foo that takes an AVar type to be called otherwise if a const is passed for the AConst version to be called.

#include <iostream>

template <typename T>
struct AConst
{
   AConst(T x):t(x){}
   const T t;
};

template <typename T>
struct AVar
{
   AVar(const T& x):t(x){}
   const T& t;
};

template <typename T>
void foo(AConst<T> a) { std::cout << "foo AConst\n"; }

template <typename T>
void foo(AVar<T>   a) { std::cout << "foo AVar\n";   }

int main()
{
   int i = 2;

   foo(1);
   foo(i);

   return 0;
}

Currently the compiler gives me an ambiguity error. Not sure how to resolve it.

UPDATE: Based on Leonid's answer with a slight modification, here is the following solution which works as required:

template <typename T>
void foo_x(AConst<T> a) { std::cout << "foo AConst\n"; }

template <typename T>
void foo_x(AVar<T>   a) { std::cout << "foo AVar\n";   }


template <typename T>
void foo(const T& a) { foo_x(AConst<T>(a));}

template <typename T>
void foo(T& a) { foo_x(AVar<T>(a));}
Foi útil?

Solução

Compiler can not deduce your T.
To help him, simplify parameter type:

template <typename T> 
void foo(const T& a) { AConst<T> aa(a); std::cout << "foo AConst\n"; }

template <typename T> 
void foo(T& a) {  AVar<T> aa(a); std::cout << "foo AVar\n";   }  

Outras dicas

Use casting to eliminate ambiguity errors. In this case you could cast "1" as an AConst if I remember right. I don't remember the exact syntax for casting to a template type...maybe something like:

foo( (AConst<int>) 1); .. or something to that effect.

The compiler can't select appropriate function. You may want to declare 2 functions with different names:

template <typename T>
void fooConst(AConst<T> a) { std::cout << "foo AConst\n"; }

template <typename T>
void fooVar(AVar<T>   a) { std::cout << "foo AVar\n";   }

Or, you may choose to use functions you have this way:

int main()
{
   int i = 2;

   foo(AConst<int>(1));
   foo(AVar<int>(i));

   return 0;
}

In general, you doesn't provide enough information to the compiler. You're the only who knows what instance should be used in the main function. Probably, if you would describe in more details what is the purpose of this code, the solution would be more specific.

You could pass in the full class template to the function like so

#include <iostream>

template <typename T>
struct AConst
{
    AConst(T x) :t(x){ std::cout << "AConst\n"; }
    const T t;
};

template <typename T>
struct AVar
{
    AVar(const T& x) :t(x){ std::cout << "AVar\n"; }
    const T& t;
};

template <typename T1>
void foo(T1 a){}

int main()
{
    int i = 2;

    foo<AConst<int>>(1);
    foo<AVar<int>>(i);

    return 0;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top