Zadowolony Pesymista
Zadowolony Pesymista

Reputation: 73

How to get rid of an enumeral mismatch error in C++?

In the book that I found there's a code computing a square root of a given number, but the code doesn't compile. There is a lot of errors when instantiating the template. This is the code:

#include <iostream>

template
<int N, int LO=1, int HI=N> class Sqrt {
public:
    enum { mid = (LO+HI+1)/2 };

    enum { result = (N<mid*mid) ? Sqrt<N,LO,mid-1>::result : Sqrt<N,mid,HI>::result };
};

template<int N, int M> class Sqrt<N,M,M> {
public:
    enum { result=M };
};

int main()
{
    std::cout << Sqrt<5>::result << std::endl;
}

and many of the warnings are

enumeral mismatch in conditional expression 'Sqrt<5,1,1>::< anonymous enum> vs 'Sqrt<5,2,2>::< anonymous enum>' [-Wenum-compare]    

as I tested later this warning is not critical, for example in the code

class a {
public:
    enum {test = 0};
};

class b {
public:
    enum {test = 1};
};

class c {
public:
    enum {test = 2 < 3 ? a::test : b::test};
};

int main()
{
    int v = c::test;
}

I get the same warning, but the code compiles. My confusion is caused because if I place the '-Wenum-compare' in compiler options, the first code compiles. What is the real problem here?

Upvotes: 0

Views: 1688

Answers (2)

NathanOliver
NathanOliver

Reputation: 180500

To get rid of the warning you can cast the enums into their integer values. This means you have two integers instead of two different enumerations.

template
<int N, int LO=1, int HI=N> class Sqrt {
public:
    enum { mid = (LO+HI+1)/2 };

    enum { result = (N<mid*mid) ? static_cast<int>(Sqrt<N,LO,mid-1>::result) : static_cast<int>(Sqrt<N,mid,HI>::result) };
};

template<int N, int M> class Sqrt<N,M,M> {
public:
    enum { result=M };
};

int main()
{
    std::cout << Sqrt<5>::result << std::endl;
}

Will compile without warning. As for why you get these warnings even though it compiles see: Why do I get an error when directly comparing two enums?

Upvotes: 1

R Sahu
R Sahu

Reputation: 206577

Instead of enum, you can use static constexpr int.

template <int N, int LO=1, int HI=N> struct Sqrt {
    static constexpr int mid = (LO+HI+1)/2;
    static constexpr int result = (N<mid*mid) ? Sqrt<N,LO,mid-1>::result : Sqrt<N,mid,HI>::result;
};

template<int N, int M> struct Sqrt<N,M,M> {
    static constexpr int result=M;
};

Upvotes: 1

Related Questions