函数模板的模糊重载
ambiguous overload of function template
这段(人为的)代码:
#include <iostream>
template<typename T> class Foo
{
public:
Foo(int i) : i_(i) {}
private:
int i_;
};
template<typename T>
Foo<T> bar(const T& /*x*/, const Foo<T>& /*foo*/)
{
std::cout << "first bar()" << std::endl;
return Foo<T>(1);
}
template<typename T>
Foo<T> bar(int /*x*/, const Foo<T>& /*foo*/)
{
std::cout << "second bar()" << std::endl;
return Foo<T>(42);
}
int main()
{
Foo<bool> f1(0);
Foo<bool> f2 = bar(true, f1); // first bar()
Foo<bool> f3 = bar(10, f1); // second bar()
(void)f2; // avoid warning for unused variable
(void)f3; // avoid warning for unused variable
return 0;
}
的作用不大,但在g++ 4.7.2下编译得很好:
$ g++ -std=c++11 -Wall -Wextra foo.cpp
,它产生预期的结果:
$ ./a.out
first bar()
second bar()
当我在main()
中将模板类型从bool
更改为int
时:
int main()
{
Foo<int> f1(0);
Foo<int> f2 = bar(true, f1); // first bar()
Foo<int> f3 = bar(10, f1); // second bar()
(void)f2; // avoid warning for unused variable
(void)f3; // avoid warning for unused variable
return 0;
}
我得到一个编译错误:
$ g++ -std=c++11 -Wall -Wextra foo.cpp
foo.cpp: In function 'int main()':
foo.cpp:30:29: error: call of overloaded 'bar(int, Foo<int>&)' is ambiguous
foo.cpp:30:29: note: candidates are:
foo.cpp:13:8: note: Foo<T> bar(const T&, const Foo<T>&) [with T = int]
foo.cpp:20:8: note: Foo<T> bar(int, const Foo<T>&) [with T = int]
问题是bar()
的两个版本在这种情况下发生冲突,编译器无法决定选择哪个。
如何解决这个问题?
可以使用struct的部分模板特化,如:
namespace detail
{
template <typename T1, typename T2> struct bar;
template <typename T> struct bar<T, T>
{
Foo<T> operator()() const
{
std::cout << "first bar()" << std::endl;
return Foo<T>(1);
}
};
template <typename T> struct bar<int, T>
{
Foo<T> operator()() const
{
std::cout << "second bar()" << std::endl;
return Foo<T>(42);
}
};
template <> struct bar<int, int>
{
Foo<int> operator()() const
{
std::cout << "third bar()" << std::endl;
return Foo<int>(42);
}
};
}
template<typename T1, typename T2>
Foo<T2> bar(const T1& /*x*/, const Foo<T2>& /*foo*/)
{
return detail::bar<T1, T2>()();
}
用
测试int main()
{
Foo<int> f1(0);
Foo<int> f2 = bar<int>(true, f1); // first bar()
Foo<int> f3 = bar(10, f1); // second bar()
(void)f2; // avoid warning for unused variable
(void)f3; // avoid warning for unused variable
return 0;
}
或
int main()
{
Foo<bool> f1(0);
Foo<bool> f2 = bar(true, f1); // first bar()
Foo<bool> f3 = bar(10, f1); // second bar()
(void)f2; // avoid warning for unused variable
(void)f3; // avoid warning for unused variable
return 0;
}
标签调度:
struct selector {};
template<typename T>
Foo<T> bar(const T& /*x*/, const Foo<T>& /*foo*/, const selector&)
{
std::cout << "first bar()" << std::endl;
return Foo<T>(1);
}
// call it
bar(1, f1, selector{});
这只是一个例子,假设有更多的重载,需要更复杂。
正如Johan正确指出的那样,enable_if只作用于模板方法。
如果你可以使用参数给出选择选项,你可以选择你想要使用的栏,这可以消除歧义。我希望这能帮到你。
#include <iostream>
template<typename T> class Foo
{
public:
Foo(int i) : i_(i) {}
private:
int i_;
};
template<typename T>
Foo<T> bar(const T& /*x*/, const Foo<T>& /*foo*/,int pick=0)
{
std::cout << "first bar()" << std::endl;
return Foo<T>(1);
}
template<typename T>
Foo<T> bar(int /*x*/, const Foo<T>& /*foo*/,double pick=0)
{
std::cout << "second bar()" << std::endl;
return Foo<T>(42);
}
int main()
{
Foo<bool> f1(0);
Foo<int> f15(0);
Foo<bool> f2 = bar(true, f1); // first bar()
Foo<int> f3 = bar(10, f15,1); // first bar()
Foo<int> f35 = bar(10, f15,1.0); // second bar()
(void)f2; // avoid warning for unused variable
(void)f3; // avoid warning for unused variable
return 0;
}
相关文章:
- 继承函数的重载解析
- 你能重载对象变量名本身返回的内容吗
- 从父命名空间重载类型
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 类X有多个默认构造函数和对重载函数的模糊调用
- Visual Studio不允许我使用sqrt或floor,对重载函数的模糊调用
- JsonCpp 仅在 Windows 中出现模糊的重载
- 模糊的C++运算符重载
- 在Windows上为Matlab构建libspline - 对重载函数'pow'的模糊调用
- 非成员函数中的隐式参数转换模糊性使用std::函数重载
- c++中的函数重载模糊性
- GCC vs clang -使用' make_overload '可变lambda继承时的模糊重载
- 函数模板的模糊重载
- 无参数可变模板上的模糊重载
- Visual Studio 2012中嵌套boost::assign:list_of失效-对重载函数的模糊调用
- 以指针形式传递数组的模糊重载
- 模板形参的模糊模板重载是一个容器
- G++:模糊情况下的默认重载
- gcc中的模糊重载,msvc没问题