Silverlan
Silverlan

Reputation: 2911

"Expected a statement" in constexpr if else expression

I have a function test, which prints out the underlying type of an enum parameter:

enum class TestEnum : uint32_t
{

};

template<typename TEnum>
    void test(TEnum v)
{ // Line 12
    if constexpr (std::is_same_v<std::underlying_type_t<TEnum>,int8_t>)
        std::cout<<"int8"<<std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>,uint8_t>)
        std::cout<<"uint8"<<std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>,int16_t>)
        std::cout<<"int16"<<std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>,uint16_t>)
        std::cout<<"uint16"<<std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>,int32_t>)
        std::cout<<"int32"<<std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>,uint32_t>)
        std::cout<<"uint32"<<std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>,int64_t>)
        std::cout<<"int64"<<std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>,uint64_t>)
        std::cout<<"uint64"<<std::endl;
    else
        static_assert(false,"Unsupported enum type!");
}

int main(int argc,char *argv[])
{
    TestEnum e {};
    test<TestEnum>(e);
    return EXIT_SUCCESS;
}

The program compiles and runs fine in Visual Studio 2017 (with ISO C++17), however the last else is underlined in red with the following message:

expected a statement

detected during instantiation of "void test(TEnum v) [with TEnum=TestEnum]" at line 12

Program code with last 'else' underlined in red.

(I've tried using else constexpr instead of just else, but that doesn't seem to matter.)

If I remove the last else if-branch (the one checking for uint64_t), the error disappears:

Program code without the last 'else if'-branch, and no error message.

Is this a bug in Visual Studio, or am I doing something that I shouldn't?

Upvotes: 2

Views: 1227

Answers (2)

Andriy Tylychko
Andriy Tylychko

Reputation: 16256

it seems to be a bug in IntelliSense. It's not related with uint64_t or any other type. Everything above 8 if/else branches start to produce this error. Feel free to report to Microsoft

Upvotes: 0

PilouPili
PilouPili

Reputation: 2699

I am sure this is not actually the answer you expected but… this code

enum class TestEnum : uint32_t
{

};

template<typename TEnum>
void test(TEnum v)
{ // Line 12
    if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, int8_t>)
    {
        std::cout << "int8" << std::endl;
    }
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, uint8_t>)
    {
        std::cout << "uint8" << std::endl;
    }
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, int16_t>)
    {
        std::cout << "int16" << std::endl;
    }
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, uint16_t>)
    {
        std::cout << "uint16" << std::endl;
    }
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, int32_t>)
    {
        std::cout << "int32" << std::endl;
    }
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, uint32_t>)
    {
        std::cout << "uint32" << std::endl;
    }
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, int64_t>)
    {
        std::cout << "int64" << std::endl;
    }
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, uint64_t>)
    {
        std::cout << "uint64" << std::endl;
    }
    else
    {
        static_assert(false, "Unsupported enum type!");
    }
}

int main(int argc, char *argv[])
{
    TestEnum e{};
    test<TestEnum>(e);
    return EXIT_SUCCESS;
} 

does not produce any warning

enter image description here

however

enum class TestEnum : uint32_t
{

};

template<typename TEnum>
void test(TEnum v)
{ // Line 12
    if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, int8_t>)
        std::cout << "int8" << std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, uint8_t>)
        std::cout << "uint8" << std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, int16_t>)
        std::cout << "int16" << std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, uint16_t>)
        std::cout << "uint16" << std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, int32_t>)
        std::cout << "int32" << std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, uint32_t>)
        std::cout << "uint32" << std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, int64_t>)
        std::cout << "int64" << std::endl;
    else if constexpr (std::is_same_v<std::underlying_type_t<TEnum>, uint64_t>)
        std::cout << "uint64" << std::endl;
    else
        static_assert(false, "Unsupported enum type!");
}

int main(int argc, char *argv[])
{
    TestEnum e{};
    test<TestEnum>(e);
    return EXIT_SUCCESS;
}

produces the same message as in your first screen capture. I know it's french but trust me it says the same.

enter image description here

Just for the debate I never really understood why the norm still allows

if(boolean) do;

while

if(boolean) { do;}

does the job and with no ambiguity whatsoever. Surely a dirty heritage of what Fortran 77 allowed. Frankly 40 years has past and we are not about to scream if we have to add two more characters... Well I am not...

Upvotes: 1

Related Questions