указать на функцию-член. Извините, я больше не буду отвечать, я сделал все возможное, чтобы попытаться объяснить, и я просто повторяюсь

тении[Expr.prim.id], увидишь, что

Выражение id, которое обозначает нестатический член данных или нестатическую функцию-член класса, может использоваться только:

если это id-выражение обозначает нестатический элемент данных и появляется в неоцененном операнде.

Тот факт, что вышеприведенный пункт относится только к элементам данных, мне неясен. Интуитивно я ожидаю, что следующее будет правильно сформировано:

#include <type_traits>

using func = int();

class bar {
  func foo; // This is valid, and not the subject of the question
};

static_assert(std::is_same<decltype(bar::foo), func>::value, "No Symmetry!");

Ноdecltype() плохо сформирован еще до того, как проверено статическое утверждение.

Есть ли какая-то двусмысленность, по которой я скучаю?

Ответы на вопрос(3)

Посмотри на это:

typedef void Func();

Func freeFunction;

struct Foo {
    Func memberFunction;
};

freeFunctionобъявлениеFunc freeFunction;, Так,decltype(freeFunction) являетсяvoid()т.е.Func.

Используя ту же логику, что иFoo::memberFunction объявлен какFunc тоже я бы ожидалdecltype(Foo::memberFunction) бытьFunc слишком. Но это не так, так как это не компилируется.

Так же, какint a; decltype(a) решает вint, даже еслиint a; является членом,decltype(Foo::memberFunction) должно быть хорошо.

Обратите внимание, что квалификаторы также могут быть обработаны, в них нет ничего особенного (конечно, в этом случае,Func может использоваться только для объявления нестатических функций-членов):

typedef void Func() const volatile &&;

struct Foo {
    Func memberFunction;
};

Здесь я бы ожидал, чтоdecltype(Foo::memberFunction) бытьvoid() const volatile &&так что я могу скопировать его декларацию:

struct Bar {
    decltype(Foo::memberFunction) myMemFn;
};

Цитата из стандарта C ++ 14 (9.2 / 11):

[Примечание: тип нестатической функции-члена является обычным типом функции, а тип нестатического члена-данных является обычным типом объекта. Не существует специальных типов функций-членов или типов данных-членов. - конец примечания]

Эта цитата означает, что было бы разумно, еслиdecltype(<member_function>) вернул тип обычной функции.

 rustyx13 нояб. 2017 г., 19:46
Так почему же стандарт не позволяет этого?
 M.M14 нояб. 2017 г., 01:51
Это, кажется, не отвечает на вопрос, все, что вы говорите, это то, что вы не знаете, и вы ожидаете чего-то
 geza14 нояб. 2017 г., 01:54
@ М.М .: нет. Я говорю, что не вижу причин. Возможно, потому что нет ни одного. Кстати, мои ожидания не так?
 geza13 нояб. 2017 г., 19:50
@RustyX: хороший вопрос. Я не знаю. Может быть, есть веская причина не допустить этого, но я этого не вижу. Я не совсем согласен с объяснением StoryTeller. И еще не было никаких других идей.
 M.M14 нояб. 2017 г., 02:24
Тип функции-члена объявлен какFunc не являетсяFunc, Вызов этого требует одного дополнительного параметра (который синтаксически появляется перед круглыми скобками вызова функции), и параметры являются частью типа. Элементы данных не работают так. Вы можете использоватьint * указать на член данных int. Вы не можете использоватьFunc * указать на функцию-член. Извините, я больше не буду отвечать, я сделал все возможное, чтобы попытаться объяснить, и я просто повторяюсь

Я так не думаю. Вероятно, больше того, что была определенная необходимость оценивать нестатические элементы данных, и не столько для нестатических функций-членов.

Однако это:

static_assert(std::is_same<decltype(bar::foo), func>::value, "No Symmetry!");

не имеет особого смысла. Тип&bar::foo не являетсяfunc*, егоfunc bar::*, И нет способа записать это без указателя, поэтому нужно иметь возможность оценитьdecltype(bar::foo) означает введение совершенно нового синтаксиса типа? Кажется, не стоит.

Обратите внимание, чтоdecltype(bar::foo) не может бытьfunc потому чтоfunc это тип функции, ноbar::foo является функцией-членом.

 Barry14 нояб. 2017 г., 01:59
@geza Я прочитал вопрос, да.
 geza14 нояб. 2017 г., 02:11
Почему? Decltype'ing переменную-член, она дает ее тип, не будучи "специализированным" для включающего класса. Мы могли бы иметь то же самое для функций.
 geza23 нояб. 2017 г., 14:13
Это интересно:stackoverflow.com/questions/47455800/..., Цитата из стандарта: «Тип нестатической функции-члена является обычным типом функции, а тип нестатического члена-данных является обычным типом объекта».
 geza14 нояб. 2017 г., 01:55
этоdecltype(bar::foo), без&.
 geza14 нояб. 2017 г., 02:01
Тогда я не понимаю ваш ответ. Почему вы говорите об указателях, когда вопрос не имеет никаких?decltype(bar::foo) мог вернутьсяint()Я не вижу никаких проблем с этим.

Дело в том, что существует много информации о типах, которая добавляется как часть этого объявления функции-члена.

Покаfunc конечно, может быть использован для объявления этого члена, история не заканчивается здесь. Как только член объявлен, его тип завершен. Это включает в себя добавление нескольких других вещей, таких какCV-qualifers а такжереф-классификаторы, На случай, еслиfooвсе неявные по умолчанию определены, и они становятся частьюbar::fooтип. Как указано[Dcl.fct] / 8:

Тип возвращаемого значения, список параметров-типов, квалификатор ref, cv-qualifier-seq и спецификация исключения, но не аргументы по умолчанию, являются частью типа функции.

Там нет никакого способа указать их явно в приведенной выше декларацииfoo (хотя они могут быть добавлены кfunc), но они могут быть добавлены в целом:

class bar {
  int foo() const volatile &&;
};

Они являются частью типа функции, иdecltype(bar::foo) следует обратиться к ним, если они появятся (и если я соберусь правильно, даже если они не будут).

Гдеconst volatile && идти, когда мы пытаемся оценитьdecltype(bar::foo)?

Должно ли это быть проигнорировано? Это можно сделать. Но потеря информации о типе редко бывает хорошей вещью.Должны ли мы сохранить его, и типdecltype оценивает быть указателем на функцию-член?
Это тоже сработало бы, но теперь оно отличается от того, как будут вести себя элементы данных при именовании в неоцененном контексте. Введем несоответствие.Должно ли оно быть сохранено, а тип разрешен во что-то еще? Возможно что-то вродеint(foo const volatile&&) или жеint() const volatile && (другая форма типа функции)? Это нарушает симметрию, которую можно было бы ожидать, и снова является несоответствием элементам данных.

Нет простого или очевидного способа, с помощью которого это всегда будет работать хорошо. Таким образом, вместо того, чтобы усложнять задачу для функции, которая будет иметь ограниченное использование, лучше рассматривать ее как плохо сформированную.

 StoryTeller13 нояб. 2017 г., 13:11
@Quentin - Вы можете надеть этоfuncВы не можете добавить его после фактаbar::foo, Я уточнил, что я имел в виду.
 Quentin13 нояб. 2017 г., 13:02
Если неЭта бумага устарела, кажется, что на самом деле можно поставитьconst volatile && в typedef.
 aschepler13 нояб. 2017 г., 13:35
Я не знаю, я думаю, что я согласен с Квентином, что это "очевидно", еслиdecltype(bar::foo) работает, ваш пример должен привести кint()const volatile&&, (И еслиfoo были бы перегружены, программа просто была бы плохо сформирована.) Я больше думаю, что она не была сочтена достаточно полезной для определения и реализации.
 Quentin13 нояб. 2017 г., 13:26
Это спорно:decltype элемента данных специально определено как его «базовый» тип (как если бы это была свободная переменная), но затем&Foo::bar будет выдавать различные типы в зависимости от того, является ли элемент данныхbar являетсяstatic или нет. Может быть, я запутался, но для меняdecltype симметрия с членами данных будет достигнута путем возврата квалифицированного типа функции, даже если этот тип «отвратителен» и, следовательно, вряд ли пригоден для использования.
 Quentin13 нояб. 2017 г., 13:14
Вы имеете в виду нетfunc foo const;? Хорошо, но как это будет обоснование, которое мешаетdecltype(bar::foo) от создания полностью квалифицированного типа функции, т.е.int() const volatile && в твоем примере?

Ваш ответ на вопрос