While working with ref-qualified function overloads, I'm getting different results from GCC (4.8.1) and Clang (2.9 and trunk). Consider the following code:
#include <iostream>
#include <utility>
struct foo
{
int& bar() &
{
std::cout << "non-const lvalue" << std::endl;
return _bar;
}
//~ int&& bar() &&
//~ {
//~ std::cout << "non-const rvalue" << std::endl;
//~ return std::move(_bar);
//~ }
int const& bar() const &
{
std::cout << "const lvalue" << std::endl;
return _bar;
}
int const&& bar() const …
Run Code Online (Sandbox Code Playgroud) 最近我了解到function's reference qualifiers
,例如
struct foo
{
void bar() {}
void bar1() & {}
void bar2() && {}
};
Run Code Online (Sandbox Code Playgroud)
我可能需要此功能的地方,这个语言功能是否有任何实际用例?
任何人都可以解释为什么编译器(g ++,visual c ++)在这种情况下无法推断模板参数?
struct MyClass
{
void Foo(int x)& {}
void Foo(int x)&& {}
};
template<typename T>
void CallFoo(void(T::*func)(int)&)
{
//create instance and call func
}
int main()
{
CallFoo(&MyClass::Foo); // Fails to deduce T
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器不能将T推导为MyClass?这仅适用于ref限定符重载的方法.如果方法被const-ness或参数类型重载,一切正常.在这种情况下,似乎只有Clang才能推断T.
在下面的C++ 11 +代码中,返回语句构造应该是首选吗?
#include <utility>
struct Bar
{
};
struct Foo
{
Bar bar;
Bar get() &&
{
return std::move(bar); // 1
return bar; // 2
}
};
Run Code Online (Sandbox Code Playgroud) 如果没有另一个超载(比如,f(T &)
或f(volatile T &&)
一个(部件)函数模板的)template< typename T > f(T &&);
,然后T &&
是所谓的转发参考,并且T
要么是U
,或U &
对于一些CV-合格类型U
.但是对于成员函数的cv-ref-qualifiers,没有这样的规则.在struct S { void f() && { ; } };
一个S::f()
总是rvalue-reference限定符.
在通用代码中volatile
,如果所有这些函数通常都做同样的事情,那么避免定义4(甚至8,如果我们也考虑限定符)某些成员函数的重载将是非常有用的.
中出现的这种方式的另一个问题,这是不可能的,以限定一个有效的CV-REF-限定符的*this
在特定的意义.以下代码不允许确定成员函数的ref限定符operator ()
是否&&
为&
.
#include <type_traits>
#include <utility>
#include <iostream>
#include <cstdlib>
#define P \
{ \
using this_ref = decltype((*this)); \ …
Run Code Online (Sandbox Code Playgroud) 这在clang 3.3中编译得很好:
template <typename T>
struct M;
template <typename R, typename C, typename... A>
struct M <R (C::*)(A...)> { };
template <typename R, typename C, typename... A>
struct M <R (C::*)(A...) &> { };
Run Code Online (Sandbox Code Playgroud)
但在gcc 4.8.1中失败了:
[...] error: redefinition of ‘struct M <R (C::*)(A ...)>’
struct M <R (C::*)(A...) &> { };
^
[...] error: previous definition of ‘struct M <R (C::*)(A ...)>’
struct M <R (C::*)(A...)> { };
^
Run Code Online (Sandbox Code Playgroud)
在不同的上下文中使用时,会导致各种意外的编译器行为,如崩溃或内部编译器错误.
我理解ref-qualified成员函数在标准中称为"*this的右值引用"(N2439),并受gcc 4.8.1支持.
这里的问题是将它们用作模板参数,其中gcc似乎不区分ref-qualified和普通成员函数类型.
clang的std库实现似乎检测是否支持此功能
__has_feature(cxx_reference_qualified_functions) …
Run Code Online (Sandbox Code Playgroud) 给出以下转换运算符
struct A
{
template<typename T> explicit operator T&& () &&;
template<typename T> explicit operator T& () &;
template<typename T> explicit operator const T& () const&;
};
struct B {};
Run Code Online (Sandbox Code Playgroud)
我希望以下转换都是有效的,但有些会给出编译错误(实例):
A a;
A&& ar = std::move(a);
A& al = a;
const A& ac = a;
B&& bm(std::move(a)); // 1. OK
B&& bt(A{}); // 2. OK
B&& br(ar); // 3. error: no viable conversion from A to B
B& bl(al); // 4. OK
const B& bz(al); // 5. …
Run Code Online (Sandbox Code Playgroud) c++ rvalue-reference conversion-operator c++11 ref-qualifier
当用G ++(gcc 4.8.1和MinGW 4.8.2 with -std=gnu++1y
flag)编译我的代码时,我发现了一个奇怪的行为.在SSCCE的精神中,我隔离了以下代码段:
struct C
{
template< typename X >
auto
f(X &&) const &
{ ; }
template< typename X >
auto
f(X &&) &
{ ; }
template< typename X >
auto
f(X &&) &&
{ ; }
};
int main()
{
int i{};
#if 1
C{}.f(i);
#endif
#if 1
C c{};
c.f(i);
#endif
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它给出了一个错误:
main.cpp: In function 'int main()':
main.cpp:29:10: error: call of overloaded …
Run Code Online (Sandbox Code Playgroud) 以下代码会导致未定义的行为:
class T
{
public:
const std::string& get() const { return s_; }
private:
std::string s_ { "test" };
}
void breaking()
{
const auto& str = T{}.get();
// do sth with "str" <-- UB
}
Run Code Online (Sandbox Code Playgroud)
(因为const&
根据我的理解,生命周期延长不适用于此处)。
为了防止这种情况,一种解决方案可能是添加一个引用限定符get()
以防止在 LValues 上调用它:
const std::string& get() const & { return s_; }
Run Code Online (Sandbox Code Playgroud)
但是,由于函数现在既是const
又是&
合格的,因此仍然可以调用get()
RValues,因为它们可以分配给const&
:
const auto& t = T{}; // OK
const auto& s1 = t.get(); // OK
const auto& s2 = …
Run Code Online (Sandbox Code Playgroud) 在 C++ 中,不能在一个类中用没有 ref-qualifier 的成员函数重载带有 ref-qualifier 的成员函数。但同时可以从父类继承一个成员函数并在子类中重载它,如示例所示:
struct A {
void f() {}
//void f() & {} //overload error everywhere
};
struct B : A {
using A::f;
void f() & {} //ok everywhere
};
int main() {
B b;
b.f(); //ok in GCC only
}
Run Code Online (Sandbox Code Playgroud)
只是在调用的过程中f
,Clang抱怨道call to member function 'f' is ambiguous
。但GCC接受程序没有任何错误,演示: https: //gcc.godbolt.org/z/5zzbWcs97
这里是哪个编译器?
c++ overloading language-lawyer ref-qualifier function-qualifier
c++ ×10
ref-qualifier ×10
c++11 ×7
c++17 ×2
overloading ×2
templates ×2
c++14 ×1
return-value ×1