C ++ 0x: условный оператор, xvalues ​​и decltype - PullRequest
3 голосов
/ 12 октября 2010

Я публикую здесь comp.std.c ++ Usenet обсуждение , потому что эта группа стала очень ненадежной. Последние несколько сообщений, которые я отправил туда, ушли в пустоту, и активность почти прекратилась. Я сомневаюсь, что меня забанили и / или все остальные просто потеряли интерес. Надеемся, что все заинтересованные люди найдут это обсуждение, и будет общая миграция. Может быть, тогда они назначат нового модератора.


Hello!

С моей текущей интерпретацией проекта N3126 w.r.t. условный оператор и xvalues, я ожидаю, что следующие утверждения будут выполнены:

 int i = 0;
 int& j = true? i : i;
 int&& k = true? std::move(i) : std::move(i);   // #2
 assert(&i == &j); // Holds since C++98
 assert(&i == &k); // Should this hold as well?

5.16 / 4 говорит:

Если второй и третий операнды [к условный оператор] являются глвалы той же ценностной категории и имеют один и тот же тип, результат этого типа и категории значения [...]

Хотя в нем четко не сказано, что полученное значение glvalue относится к один из объектов, на которые ссылаются операнды glvalue - или это подразумевается, потому что в противном случае он вернул бы prvalue? Использование GCC 4.5.1 в режиме C ++ 0x второе утверждение не выполняется. Ссылка k кажется обратитесь к некоторому временному объекту. Может кто-нибудь уточнить, является ли компилятору разрешено создавать такой временный объект, если оба операнда вокруг двоеточия xvalues ​​одного типа?

В настоящее время я предполагаю, что GCC содержит ошибки и / или не соответствует современным требованиям. в xvalues.

Следующий вопрос: не было бы неплохо иметь возможность обнаружить категория значения выражения? Если мы игнорируем условный оператор мы можем определить категорию значения выражения с помощью decltype. Но что такое

 bool xvalue = std::is_rvalue_reference<
   decltype( true ? std::move(i) : std::move(i) ) >::value;

предполагается уступить? Используя GCC 4.5.1, переменная xvalue инициализируется с ложным Соответствует ли это текущему стандартному проекту?

ТИА, Себастьян

1 Ответ

2 голосов
/ 12 октября 2010

Я думаю, что GCC 4.5.1 не соответствует требованиям §5.16 / 4. Вы подали отчет об ошибке ?

Во всяком случае, я думаю, что это соответствует этому троичному коду оператора. decltype определяется §7.1.6.2 / 4:

Тип, обозначаемый decltype (e): определяется следующим образом:

  • если e - не выраженное в скобках id-выражение или доступ к члену класса (5.2.5), decltype (e) является типом сущность, названная е. Если нет такой сущности, или если е называет набор перегруженные функции, программа плохо сформированы;
  • в противном случае, если e является вызовом функции (5.2.2) или вызовом перегруженный оператор (скобки вокруг е игнорируются), decltype (е) тип возврата статически выбранная функция;
  • в противном случае, если e - lvalue, decltype (e) - T &, где T - тип е;
  • в противном случае decltype (e) является типом e. Операнд типа decl спецификатор является неоцененным операндом (Пункт 5).

decltype работает, извлекая соответствующее объявление и возвращая из него нужный тип. У него мало интеллекта в отношении не перегруженных операторов. Возможно, еще один момент

  • в противном случае, если e является xvalue, decltype (e) будет T&&, где T является типом e

будет в порядке, особенно потому, что, как написано, xvalues ​​обрабатываются как prvalues. Кроме того, ваше выражение точно соответствует определению std::common_type (§20.7.6.6 / 3).

Один простой обходной путь (для обозначения фразы: vP):

template< typename T1, typename T2 >
struct common_type_and_category {
    typedef typename std::conditional<
        std::is_same< T1, T2 >::value,
        T1,
        typename std::common_type< T1, T2 >::type
    >::type type;
};
...