小编Dou*_*oug的帖子

C++ 0x右值引用 - lvalues-rvalue绑定

这是C++ 0x右值引用和临时值的后续问题

在上一个问题中,我询问了这段代码应该如何工作:

void f(const std::string &); //less efficient
void f(std::string &&); //more efficient

void g(const char * arg)
{
    f(arg);
}
Run Code Online (Sandbox Code Playgroud)

由于隐式临时似乎应该调用移动重载,这种情况发生在GCC中,而不是MSVC(或MSVC的Intellisense中使用的EDG前端).

这段代码怎么样?

void f(std::string &&); //NB: No const string & overload supplied

void g1(const char * arg)
{
     f(arg);
}
void g2(const std::string & arg)
{
    f(arg);
}
Run Code Online (Sandbox Code Playgroud)

看来,基于我之前问题的答案,该函数g1是合法的(并且被GCC 4.3-4.5接受,但不被MSVC接受).但是,GCC和MSVC都拒绝,g2因为第13.3.3.1.4/3条禁止左值绑定到rvalue ref参数.我理解这背后的基本原理 - 在N2831"使用右值参考修复安全问题"中对此进行了解释.我也认为GCC可能正如该论文的作者所预期的那样实施该条款,因为GCC的原始补丁是由其中一位作者(Doug Gregor)撰写的.

但是,我不是很直观.对我来说,(a)a const string &在概念上更接近于string &&a const char *,而且(b)编译器可以创建一个临时字符串g2,就好像它是这样编写的:

void g2(const std::string & …
Run Code Online (Sandbox Code Playgroud)

c++ lvalue rvalue-reference c++11

16
推荐指数
1
解决办法
4252
查看次数

为什么std :: type_info是多态的?

是否有理由std::type_info指定为多态?析构函数被指定为虚拟(并且在"C++的设计和演变"中对"因此它是多态的"效果进行了评论).我真的没有看到令人信服的理由.我没有任何具体的用例,我只是想知道它背后是否有任何理由或故事.


以下是我提出并拒绝的一些想法:

  1. 这是一个扩展点-实现可能定义子类,然后程序可能会尝试dynamic_cast一个std::type_info到另一个,实现定义派生类型.这可能是原因,但似乎实现添加实现定义的成员(可能是虚拟的)同样容易.希望测试这些扩展的程序无论如何都必然是不可移植的.
  2. 这是为了确保在delete使用基指针时正确销毁派生类型.但目前还没有标准的派生类型,用户不能定义有用的派生类型,因为type_info没有标准的公共构造函数,所以delete荷兰国际集团一个type_info指针是从未合法和便携.并且派生类型没有用,因为它们无法构造 - 我知道这种不可构造的派生类型的唯一用途是在is_polymorphic类型特征之类的实现中.
  3. 它保留了具有自定义类型的元类的可能性 - 每个真正的多态class A都会得到派生的"元类" A__type_info,它来源于type_info.也许这样的派生类可以暴露new A以类型安全的方式调用各种构造函数参数的成员,以及类似的东西.但type_info实际上制作多态本身实际上使得这样的想法基本上无法实现,因为你必须为你的元类创建元类,无限制,如果所有type_info对象都有静态存储持续时间,这就是一个问题.也许禁止这是使其变为多态的原因.
  4. 有一些用于将RTTI功能(除了dynamic_cast)应用于std::type_info自身,或者有人认为它很可爱,或者如果type_info不是多态的则令人尴尬.但鉴于没有标准派生类型,并且标准层次结构中没有其他类可以合理地尝试交叉投射,问题是:什么?是否有用于表达式typeid(std::type_info) == typeid(typeid(A))
  5. 这是因为实施者将创建他们自己的私有派生类型(我相信GCC会这样做).但是,为什么还要指定它呢?即使析构函数未被指定为虚拟,并且实现者决定它应该是,但是实现可以将其声明为虚拟,因为它不会更改允许的操作集type_info,因此便携式程序将无法分辨其中的不同之处.
  6. 这与部分兼容的ABI共存的编译器有关,可能是动态链接的结果.type_info如果type_info保证是虚拟的,也许实现者可以以可移植的方式识别他们自己的子类(而不是来自另一个供应商的子类).

最后一个对我来说是最合理的,但它相当弱.

c++ polymorphism rtti typeinfo

16
推荐指数
2
解决办法
1838
查看次数

C++ 0x右值引用和临时值

(我在comp.std.c ++上询问了这个问题的变体,但没有得到答案.)

为什么f(arg)在这段代码中的调用调用const ref重载f

void f(const std::string &); //less efficient
void f(std::string &&); //more efficient

void g(const char * arg)
{
     f(arg);
}
Run Code Online (Sandbox Code Playgroud)

我的直觉说f(string &&)应该选择重载,因为arg无论如何都需要转换为临时值,并且临时匹配rvalue引用比lvalue引用更好.

这不是GCC和 MSVC中发生的事情(编辑:谢谢Sumant:它不会发生在GCC 4.3-4.5中).至少在G ++和 MSVC中,任何左值都不会绑定到右值引用参数,即使创建了一个中间临时值.实际上,如果不存在const ref重载,编译器会诊断出错误.然而,编写f(arg + 0)f(std::string(arg)) 选择右值引用过载如你所愿.

从我对C++ 0x标准的阅读中,似乎在考虑是否f(string &&)可行时应考虑将const char*隐式转换为字符串,就像传递const lvalue ref参数时一样.第13.3节(重载解析)在很多地方没有区分rvalue refs和const引用.此外,似乎阻止左值绑定到右值引用(13.3.3.1.4/3)的规则不适用,如果存在中间临时值 - 毕竟,从临时值移动是完全安全的.

这是:

  1. 我误读/误解了标准,其中实现的行为是预期的行为,并且有一个很好的理由为什么我的例子应该按照它的方式行事?
  2. 编译器供应商以某种方式犯下的错误?或者是基于共同实施策略的错误?或者是其他供应商复制的GCC(首次实施此左值/右值参考绑定规则)中的错误?
  3. 标准中的缺陷,或意外后果,或应澄清的内容?

编辑:我有一个相关的后续问题:C++ 0x rvalue引用 - lvalues-rvalue绑定

c++ temporary rvalue-reference c++11

14
推荐指数
2
解决办法
2967
查看次数

本地类模板

我们可以在函数内部定义一个本地类,但是这个类不能是一个有点烦人且不一致的模板.在C++ 0x标准中是否有任何更新?

c++ templates c++11

13
推荐指数
1
解决办法
3173
查看次数

如何为所有派生类型部分专门化类模板?

我想部分专门化一个现有的模板,我无法改变(std::tr1::hash)基类和所有派生类.原因是我使用奇怪的重复模板模式进行多态,并且哈希函数在CRTP基类中实现.如果我只想部分专门用于CRTP基类,那么它很简单,我可以写:


namespace std { namespace tr1 {

template <typename Derived>
struct hash<CRTPBase<Derived> >
{
    size_t operator()(const CRTPBase<Derived> & base) const 
    { 
        return base.hash(); 
    }
};

} }
Run Code Online (Sandbox Code Playgroud)

但是这种专门化只与实际的派生类不匹配CRTPBase<Derived>.我想要的是一种编写部分特化的方法,Derived当且仅当它来源于CRTPBase<Derived>.我的伪代码是


namespace std { namespace tr1 {

template <typename Derived>
struct hash<typename boost::enable_if<std::tr1::is_base_of<CRTPBase<Derived>, Derived>,
    Derived>::type>
{
    size_t operator()(const CRTPBase<Derived> & base) const 
    { 
        return base.hash(); 
    }
};

} }
Run Code Online (Sandbox Code Playgroud)

......但是,这并不工作,因为编译器不能告诉大家,enable_if<condition, Derived>::typeDerived.如果我可以更改std::tr1::hash,我只需添加另一个虚拟模板参数boost::enable_if,如enable_if文档所建议的那样,但这显然不是一个很好的解决方案.有没有解决这个问题的方法?我是否必须在每个unordered_set或 …

c++ partial-specialization derived-class crtp

9
推荐指数
1
解决办法
4381
查看次数