在模版类型推导中,引用被推导成什么类型?

topikachu 2003-06-30 10:08:13
首先看一个例子
struct foo{};

template <typename T>
void bar(T)
{
typedef T& myT;
};

int main()
{
foo aFoo;
foo& rFoo(aFoo);
bar ( rFoo);
}

在这里template <typename T>void bar(T) 中,T被推导成什么类型?foo?foo&?

再看这个例子
struct foo{};

void goo(foo &)
{
}

template <typename rtType,typename ArgType>
void dee( rtType(*pf)(ArgType) )
{
typedef ArgType& myT;
}

int main()
{
dee(goo);
}

这个例子编译不成功,为什么?ArgType被推导成什么?
...全文
74 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
topikachu 2003-06-30
  • 打赏
  • 举报
回复
re:beijingshizi(菜青虫)
那同样是引用,为何有时推导是非引用类型,有时是引用类型呢?
beijingshizi 2003-06-30
  • 打赏
  • 举报
回复
rFoo
topikachu 2003-06-30
  • 打赏
  • 举报
回复
re:Muf(沐枫)
谢谢你的答复

那请问,第一个例子中
bar ( rFoo);
这个rFoo也是引用,这个又被推导成什么呢?
Muf 2003-06-30
  • 打赏
  • 举报
回复
ArgType 推导成 foo&
然后,myT被定义成 foo&&, 而C++中,引用的引用是不合法的。
topikachu 2003-06-30
  • 打赏
  • 举报
回复
thx xueweizhong(薛卫忠):
不过是不是应该
typedef typename UnRef<Arg>::type& myT;

:)



实际的问题是因为这样产生的
有一个现有的函数
bool foo(const bar&)

现在要在stl算法中配接,对返回值进行否定
所以写成
not1(fun_ptr(foo))
结果发生ref to ref错误
查看原代码
首先fun_ptr返回pointer_to_unary_function,将其中的argument_type类型推导成bar&,然后not1生成的unary_negate使用了上面的argument_type。
而unary_negate的
bool operator()(const argument_type& x) const又对argument_type进行了一次引用


stl的bug?或者是我用错了?
xueweizhong 2003-06-30
  • 打赏
  • 举报
回复
规则:C++98 STD/14.8.2.1:
Type deduction is done for each function template argument that is not
explicitly specified. The type of the parameter of the function tem-
plate (call it P) is compared to the type of the corresponding argu-
ment of the call (call it A)

If P is not a reference type:

--if A is an array type, the pointer type produced by the array-to-
pointer standard conversion (_conv.array_) is used in place of A for
type deduction; otherwise,

--if A is a function type, the pointer type produced by the function-
to-pointer standard conversion (_conv.func_) is used in place of A
for type deduction; otherwise,

--if A is a cv-qualified type, the top level cv-qualifiers of A's type
are ignored for type deduction.

If P is a cv-qualified type, the top level cv-qualifiers of P's type
are ignored for type deduction. If P is a reference type, the type
referred to by P is used in place of P for type deduction.

其他一些特殊情况...

例子1:

template <typename T>void bar(T);
Foo& arg;
bar(arg);

//按C++98STD的推导规则为:
P=T/A=FOO&-->P=FOO&=T/A=FOO&-->P的应用被剥掉:P=FOO=T/A=FOO&-->T=FOO
于是上面的调用被编译器解析为
boo<Foo>(arg); 参数类型为P=T=FOO

也就是说template <typename T>void bar(T)永远传值,不会传reference。
这一点和make_pair的用意是一样的。

要传reference请用
template<typename T>void bar(T&)

template<typename T>void bar(const T&)

例子2:
这个例子比较有意思:

template <typename Result,typename Arg>
void dee(Result (*)(Arg))
{
...
typedef Arg& myT;
...
}

P = Result(*)(Arg)

struct Foo;
void goo(Foo&)
dee(goo);

A = goo's type = void (*)(Foo&)

P=Result(*)(Arg)/A=void (*)(Foo&) -->
Result=void, Arg=Foo&, P=void(*)(Foo&) / A=void(*)(Foo&)

于是这一句
typedef Arg& ...
变成
typedef (Foo&)& ...

所以结论和Muf(沐枫)是一致的。

这个问题可以通过如下的方式解决:
template <typename T>
struct UnRef
{
typedef T type;
};
template <typename T>
struct UnRef<T&>
{
typedef T type;
};

然后dee模板函数修改为
template <typename Result,typename Arg>
void dee(Result (*)(Arg))
{
...
//typedef Arg& myT; _____
// |
// |
typedef UnRef<Arg>& myT;//<-
...
}
这样的type_traits已经被C++0X收纳为标准库扩展。参见http://www.boost.org

希望你满意这些答复。给点分,支持我一下。

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧