действует decltype несовместимо при использовании в сочетании с условным оператором - PullRequest
0 голосов
/ 13 октября 2011

При изучении некоторых новых функций C ++ 11 я заметил странность, связанную с новым ключевым словом decltype и его взаимодействием с условным оператором.

Я был очень удивлен, увидев вывод следующегопрограмма:

#include <iostream>
#include <map>

int main(void)
{
    // set up a map that associates the internal compiler-defined type_info name with a human readable name
    std::map <std::string, std::string> types;
    types[typeid(decltype(static_cast<unsigned char  >(0))).name()] = "unsigned char";
    types[typeid(decltype(static_cast<unsigned short >(0))).name()] = "unsigned short";
    types[typeid(decltype(static_cast<short          >(0))).name()] = "short";
    types[typeid(decltype(static_cast<unsigned int   >(0))).name()] = "unsigned int";
    types[typeid(decltype(static_cast<int            >(0))).name()] = "int";
    types[typeid(decltype(static_cast<float          >(0))).name()] = "float";
    types[typeid(decltype(static_cast<double         >(0))).name()] = "double";
    types[typeid(decltype(static_cast<bool           >(0))).name()] = "bool";

    std::cout << "Should be unsigned char : " << types[typeid(decltype(static_cast<unsigned char >(0))).name()] << std::endl;
    std::cout << "Should be unsigned short: " << types[typeid(decltype(static_cast<unsigned short>(0))).name()] << std::endl;
    std::cout << "Should be short         : " << types[typeid(decltype(static_cast<short         >(0))).name()] << std::endl;
    std::cout << "Should be unsigned int  : " << types[typeid(decltype(static_cast<unsigned int  >(0))).name()] << std::endl;
    std::cout << "Should be int           : " << types[typeid(decltype(static_cast<int           >(0))).name()] << std::endl;
    std::cout << "Should be float         : " << types[typeid(decltype(static_cast<float         >(0))).name()] << std::endl;
    std::cout << "Should be double        : " << types[typeid(decltype(static_cast<double        >(0))).name()] << std::endl;

    std::cout << "Expecting unsigned short: " << types[typeid(decltype(
        false ? static_cast<unsigned char  >(0) :
        true  ? static_cast<unsigned short >(0) :
        false ? static_cast<         short >(0) :
        false ? static_cast<unsigned int   >(0) :
        false ? static_cast<         int   >(0) :
        false ? static_cast<         float >(0) :
        false ? static_cast<         double>(0) :
                static_cast<         bool  >(0)
        )).name()] << std::endl;
}

, что привело к неожиданному выводу:

Should be unsigned char : unsigned char
Should be unsigned short: unsigned short
Should be short         : short
Should be unsigned int  : unsigned int
Should be int           : int
Should be float         : float
Should be double        : double
Expecting unsigned short: double

Я бы ожидал увидеть следующий вывод (обратите внимание на последнюю строку):

Should be unsigned char : unsigned char
Should be unsigned short: unsigned short
Should be short         : short
Should be unsigned int  : unsigned int
Should be int           : int
Should be float         : float
Should be double        : double
Expecting unsigned short: unsigned short

Кто-нибудь знает, почему это может происходить?Я использую GNU g ++.

Ответы [ 3 ]

8 голосов
/ 13 октября 2011

Вы должны изменить свои ожидания. Тип условного выражения зависит только от типов его операндов, не от значения его операндов.

Существует ряд правил, которые используются для определения общего типа для условного выражения из типов второго и третьего операндов. Значения второго и третьего операндов, даже если они являются константными выражениями, не учитываются.

Вам следует обратиться к стандарту за подробной информацией о правилах определения общего типа. Если общий тип не может быть найден, программа обычно плохо сформирована.

3 голосов
/ 13 октября 2011

Результирующий тип троичного выражения является общим типом для последних двух аргументов.В C ++ 11 есть черта std::common_type, которая бы получала этот тип (который, если я правильно помню, фактически реализован как decltype( false ? x : y )).

То, что вы получаете в своем последнем выражении, является типом общегодо bool, int, short, double и т. д. *

1 голос
/ 13 октября 2011

Результирующий тип условного выражения - это тип двух последних аргументов.Последние два аргумента должны быть одного типа.В вашем примере все повышается в два раза, чтобы удовлетворить это требование.Если вы добавите к выражению некоторый тип, который не может быть неявно приведен к удвоению (например, void *), произойдет ошибка компилятора.

В этом сценарии Decltype - это красная сельдьЭто поведение унаследовано от C.

...