我正在检查第一次练习的书cpp模板元编程的一些解决方案 http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?CPPTM_Answers_-_Exercise_2-0
写一个一元函数add_const_ref,如果它是a,则返回T. 引用类型,否则返回T const&
template<typename T>
struct add_const_ref
{
typedef typename boost::add_const<T>::type ct;
typedef typename boost::add_reference<ct>::type type;
};
我用c ++ 11修改了它:
template<typename T>
struct add_const_ref_type
{
typedef typename std::add_const<T>::type ct;
typedef typename std::add_lvalue_reference<ct>::type type;
};
我不明白为什么它可以参考。我希望这会添加const,即将int&
更改为`const int&amp;。
int main()
{
std::cout << std::is_same<add_const_ref_type<int &>::type, int&>::value << '\n'; // print 1
std::cout << std::is_same<add_const_ref_type<int &>::type, const int&>::value << '\n'; // print 0
return 0;
}
答案 0 :(得分:6)
你被左侧放置类型修饰符的错误所迷惑。
const int&
我的意思是,当您将const
应用于int&
时,您的const int&
是正确的吗?
错误。
要了解此处发生了什么,请在右侧上应用类型修饰符。修饰符总是适用于右边的东西;现在,把它放在左边&#34;是非法的:
int const&
是对const的引用。这实际上是有效的C ++。
int& const
这是胡说八道;您无法将const
应用于&
。 &
本身已经不可改变;只有他们所指的内容才能改变。
当您add_const<int&>
时,您从逻辑上得到int& const
;特征知道这是无稽之谈,所以返回int&
。
现在我们退一步看看如果你把它放在左边会发生什么。如果左侧没有任何内容,则特殊规则会将其应用于最左侧。所以:
const int&
只是
int const&
和
using X=int&;
const X
是
X const
再次,左边的&#34;就在最左边的部分&#34;规则。应用此功能后,我们然后展开X
:
int& const
这很明显,你总是在右边应用类型修饰符,并忽略了左侧类型修饰符的特殊情况。
解决这个问题,如果你想将const添加到值类型并使引用引用const实例,很容易修改,但通常很难解决它。毕竟,引用是一种别名,指针也是如此;当你向指针添加const
时,你得到一个const指针,而不是指向const的指针。
我怀疑作业要求您从头开始解决问题,而不是使用std
或boost
。
template<class T>
struct tag_t {using type=T;};
template<class T>
struct add_const_ref:tag_t<T>{};
template<class T>
struct add_const_ref<T&>:tag_t<T const&>{};
答案 1 :(得分:3)
它起作用,因为int & const
没有任何意义(引用总是const),因此std::add_const<int &>::type
与int &
相同。
也就是说,正在制作的部分const
不是int
。
以下是一个例子:
#include <iostream>
#include <type_traits>
int main() {
std::cout << std::is_same<int &, std::add_const<int &>::type>::value << std::endl;
std::cout << std::is_same<int, std::add_const<int>::type>::value << std::endl;
std::cout << std::is_same<int const, std::add_const<int>::type>::value << std::endl;
std::cout << std::is_same<int &, std::add_lvalue_reference<std::add_const<int &>::type>::type>::value << std::endl;
std::cout << std::is_same<int &, std::add_lvalue_reference<std::add_const<int>::type>::type>::value << std::endl;
std::cout << std::is_same<int const &, std::add_lvalue_reference<std::add_const<int>::type>::type>::value << std::endl;
}