gd1*_*gd1 8 c++ templates language-lawyer overload-resolution
上gcc 4.9.0:
#include <iostream>
#include <map>
struct A
{
typedef int type;
};
template<typename T> void foo(T*) { std::cout << "a" << std::endl; }
template<typename T> void foo(typename T::type*) { std::cout << "b" << std::endl; }
template<typename T>
struct identity
{
typedef T type;
};
template<typename T> void bar(T*) { std::cout << "a" << std::endl; }
template<typename T> void bar(typename identity<T>::type*) { std::cout << "b" << std::endl; }
int main()
{
//auto f = foo<A>; // ambiguous
foo<A>(0); // prints "b", as the second overload is more specific
auto b = bar<A>; // fine
bar<A>(0); // prints "b", as the second overload is more specific (?)
b(0); // prints "b"
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在第二种情况下,有关为何可以采取地址的任何线索?
的推导auto与模板推导相同。来自[dcl.spec.auto]:
\n\n\n当使用占位符类型声明的变量被初始化时,[...],推导的返回类型或变量类型是根据其初始值设定项的类型确定的。如果占位符是自动类型说明符,\n 则使用模板参数推导规则确定推导类型。如果占位符是
\nauto类型说明符,\n 则使用模板参数推导规则确定推导类型。
所以当我们有以下任一情况时:
\n\nauto f = foo<A>;\nauto b = bar<A>;\nRun Code Online (Sandbox Code Playgroud)\n\n我们正在执行类型推导,就像我们调用一样(借用 TC 的用词):
\n\ntemplate <typename M> void meow(M );\nmeow(foo<A> );\nmeow(bar<A> );\nRun Code Online (Sandbox Code Playgroud)\n\n并分别使用推导的类型作为和M的类型。fb
但是,根据 [temp.deduct.type],我的重点是:
\n\n\n\n\n如果模板参数仅在非推导上下文中使用并且未显式指定,则模板参数推导将失败。
\n\n非推导上下文为:
\n
\n \xe2\x80\x94 [...]
\n \xe2\x80\x94 无法进行参数推导的函数参数,因为关联的函数\n 参数是函数,或者一组重载函数(13.4),并且适用以下一个或多个:
\n \xe2\x80\x94多个函数与函数参数类型匹配(导致不明确的推导)、\n 或
\n \xe2 \x80\x94 没有函数与函数参数类型匹配,或者
\n \xe2\x80\x94 作为参数提供的函数集包含一个或多个函数模板。
\n \xe2\x80\x94 [...]
在这两种情况下,参数都是一组重载函数,其中包含一个或多个函数模板 - 这使其成为非推导上下文,因此模板参数推导失败。因此,clang 拒绝这两个初始化是正确的。
\n| 归档时间: |
|
| 查看次数: |
280 次 |
| 最近记录: |