Decltype Bug Gcc не будет компилироваться - PullRequest
0 голосов
/ 31 августа 2018

исходный код https://github.com/kennywakeland/Decltype-Bug/blob/master/main.cpp

Тестовая компиляция https://coliru.stacked -crooked.com / а / 443f03625728f00e

Этот код предназначен для тестирования сеттеров и геттеров с использованием макросов. Я хочу передать имя переменной. decltype не возвращает правильный тип в HTestSet. Любая идея, почему он не возвращает правильный тип значения?

Ошибка компилятора g ++ -std = c ++ 11 -O2 -Wall -pedantic -pthread main.cpp && ./a.out

main.cpp: In function 'int main()':
main.cpp:26:72: error: no matching function for call to 'HTestSet(TestClass&, void (BaseClass::*)(int), int&)'
     if(HTestSet(OBGEC_ON, &decltype(OBGEC_ON)::SET_CALL, test_vall_stor)){
                                                                        ^

main.cpp:18:1: note: in expansion of macro 'H_TEST_VALUE_GET_SET'
 H_TEST_VALUE_GET_SET(H_GET_VALUE(OBGEC_ON, VAL_NAME), \
 ^~~~~~~~~~~~~~~~~~~~

main.cpp:92:5: note: in expansion of macro 'H_TEST_VALUE'
     H_TEST_VALUE(woo, Green, 3);
     ^~~~~~~~~~~~

1 Ответ

0 голосов
/ 31 августа 2018

Это не ошибка (насколько я могу судить) и не имеет ничего общего с decltype. Проблема в том, что setGreen является не виртуальной функцией-членом BaseClass, и, поскольку вы не объявляли такую ​​функцию повторно в TestClass, тип:

&TestClass::setGreen

есть:

void (BaseClass::*)(int)

... и поэтому у вас есть конфликт параметров шаблона в экземпляре шаблона HTestSet.


Я не нашел стандартную цитату для этого лучше, чем пример в [expr.unary.op # 3] :

Результатом унарного оператора & является указатель на его операнд. Операндом должно быть lvalue или qualid-id . Если операндом является квалифицированный идентификатор с именем нестатического или вариантного члена m некоторого класса C с типом T, результат имеет тип «указатель на член класса C типа T ”и является prvalue, обозначающим C​::​m. [...]

struct A { int i; };
struct B : A { };
... &B::i ...       // has type int A​::​*

Использование f в начале вашего main работает только потому, что void (BaseClass::*)(int) может быть неявно преобразовано в void (TestClass::*)(int), в этом случае [conv.mem # 2] :

Значение типа «указатель на член B типа cv T», где B - тип класса, может быть преобразовано в значение типа «указатель на член D типа cv T», где D - это тип производный класс ([class.derived]) из B. [...] Поскольку результат имеет тип «указатель на член D типа cv T», косвенное обращение через него с объектом D является допустимым. Результат такой же, как если бы он направлял через указатель на член B субобъект B из D.

...