Интересный баг присутствует в компиляторе MS VC++
Следующая демонстрационная программа успешно компилируется
#include <iostream>
enum class A :int
{
a = 0, b = 1,
};
enum class B :int
{
x = 0, y = 1,
};
template <A a>
void f()
{
std::cout << "f<A> called.\n";
}
template <B b>
void f()
{
std::cout << "f<B> called.\n";
}
int main()
{
f<A::a>();
f<B::y>();
}
и выдает ожидаемый результат.
f<A> called.
f<B> called.
Но стоит добавить вызов функции для одного перечислителя, целочисленное значение которого совпадает со значением перечислителя, для которого функция уже была вызвана, как, например,
f<A::a>();
f<B::y>();
f<A::b>();
как компилятор немедленно выдает ошибку компиляции для добавленного вызова функции, что вызов функции неоднозначный:
цитата: |
Ошибка C2668 f: неоднозначный вызов перегруженной функции Сообщение может быть "void f<B::y>(void)" Сообщение или "void f<A::b>(void)" |
|
Согласно стандарту C++ 20 (9.7.1 Enumeration declarations)
цитата: |
5 Each enumeration defines a type that is different from all other types. Each enumeration also has an underlying type. The underlying type can be explicitly specified using an enum-base. For a scoped enumeration type, the underlying type is int if it is not explicitly specified. In both of these cases, the underlying type is said to be fixed. Following the closing brace of an enum-specifier, each enumerator has the type of its enumeration. |
|
Поэтому никакого неоднозначного вызова быть не должно. Имеются два различных типа перечисления, и для каждого типа перечисления определена своя шаблонная функция
f.
Представленный код успешно компилируется при использовании компиляторов
gcc или
clang.