bit-field in overload resolution for template

佐手、 提交于 2020-01-11 09:51:31

问题


Anyone knows why the first program compiles but second one doesn't? The only difference is that the first one uses normal function but the second one uses template function. Why the overload resolution behaves differently on bitfield for template and non-template function?

Please refer to paragraphs in standard when answering. Thanks.

a.cpp

struct X {
  int x : 20;
  int y : 12;
};

void f(const int& x) {}

void f(int&& x) {}

int main() {
  X x;
  f(x.x);
}

b.cpp

struct X {
  int x : 20;
  int y : 12;
};

template <typename T>
void f(T&& x) {}

template <typename T>
void f(const T& x) {}

int main() {
  X x;
  f(x.x);
}

Compiler errors:

[hidden]$ g++ -v 2>&1 | tail -n 1
gcc version 4.7.2 20120921 (Red Hat 4.7.2-2) (GCC)
[hidden]$ clang++ -v 2>&1 | head -n 1
clang version 3.3
[hidden]$ g++ -std=c++11 a.cpp
[hidden]$ g++ -std=c++11 b.cpp
b.cpp: In function ‘int main()’:
b.cpp:14:8: error: cannot bind bitfield ‘x.X::x’ to ‘int&’
[hidden]$ clang++ -std=c++11 a.cpp
[hidden]$ clang++ -std=c++11 b.cpp
b.cpp:14:5: error: non-const reference cannot bind to bit-field 'x'
  f(x.x);
    ^~~
b.cpp:2:7: note: bit-field is declared here
  int x : 20;
      ^
1 error generated.

回答1:


The error is quite clear, you cannot take non-const references to bitfields. [class.bit]/3:

The address-of operator & shall not be applied to a bit-field, so there are no pointers to bit-fields. A non-const reference shall not be bound to a bit-field (8.5.3). [ Note: If the initializer for a reference of type const T& is an lvalue that refers to a bit-field, the reference is bound to a temporary initialized to hold the value of the bit-field; the reference is not bound to the bit-field directly. See 8.5.3. —end note ]

The reason overload resolution behaves differently has to do with Universal References. Reference collapsing rules and templates make this:

template <typename T>
void f(T&& x) {}

result in T&& to be deduced as int& when applied to a non-const lvalue int, which is the case for x.x. In that particular case, you are left with:

void f(int& x){}
void f(int const& x){}

and the first one, the one obtained from reference collapsing rules on f(T&& x), it can be clearly seen to be a better match than the later one.



来源:https://stackoverflow.com/questions/14026202/bit-field-in-overload-resolution-for-template

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!