推断函数调用时出现歧义问题

时间:2013-11-22 07:29:55

标签: c++ compiler-errors overloading ambiguous-call

我有以下一些代码,它有两个版本的函数foo。我想如果为foo传递一个变量,它会调用一个AVar类型,否则如果传递一个const来调用AConst版本。

#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;
}

目前编译器给我一个模糊错误。不知道如何解决它。

更新:根据Leonid的回答进行略微修改,以下解决方案可根据需要运行:

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));}

4 个答案:

答案 0 :(得分:1)

编译器不能推断出你的。
为了帮助他,简化参数类型:

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";   }  

答案 1 :(得分:0)

使用强制转换消除歧义错误。在这种情况下,如果我没记错的话,你可以将“1”作为AConst。我不记得转换为模板类型的确切语法......可能是这样的:

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

答案 2 :(得分:0)

编译器无法选择合适的功能。您可能希望声明具有不同名称的2个函数:

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";   }

或者,您可以选择使用这种方式的功能:

int main()
{
   int i = 2;

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

   return 0;
}

通常,您没有向编译器提供足够的信息。你是唯一知道应该在main函数中使用什么实例的人。也许,如果您将更详细地描述此代码的目的是什么,那么解决方案将更加具体。

答案 3 :(得分:0)

您可以将完整的类模板传递给函数,如此

#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;
}