我遇到了一个无法理解c++中隐式转换行为的情况。 代码如下:
template <bool b, int i, unsigned... us>
void foo() {}
template <int i, unsigned... us>
void foo() {return foo<false, i, us...>();}
int main()
{
foo<true, -1, 0ul, 1ul, 2ul>(); // compiles with clang and gcc > 8 (gcc<=8 gives ambiguous function call)
foo<true, +1, 0ul, 1ul, 2ul>(); // ambiguous function call error
foo<-1, 0ul, 1ul, 3ul>(); // compiles with clang and gcc > 8 (gcc<=8 gives ambiguous function call)
foo<+1, 0ul, 1ul, 3ul>(); // ambiguous function call error
}
对于 main()
中的第 1 行和第 2 行,编译器似乎仅针对正整数将 int
隐式转换为 unsigned
(这是可以理解,但是这有什么规则吗?)
对于 main()
中的第 3 行和第 4 行,编译器似乎仅针对正整数将 int
隐式转换为 bool
。我不明白为什么。
背景:理想情况下,我想要一个类似的构造来工作,这实际上会导致 bool
模板参数的默认值。但由于参数包和 C++ 隐式内置转换,这似乎很困难。
最佳答案
非类型模板参数必须是模板参数类型的转换后的常量表达式。
转换后的常量表达式特别不允许缩小转换,在整数类型之间的常量表达式求值的情况下,这意味着如果转换会更改数值,则不允许转换。
这特定于转换的常量表达式要求。如果这些是函数参数和参数,则 -1
的隐式转换至unsigned
是被允许的,并且它也有一个明确定义的结果,尽管显然不具有相同的数值 -1
.
因此在 foo<true, -1, 0ul, 1ul, 2ul>();
需要 unsigned
的模板处于该位置 -1
作为过载候选者确实不可行。
bool 转换,表示从其他标量类型到 bool
的转换根本没有在转换常量表达式允许的转换列表中列出(请参阅 [expr.const]/10 ),据我所知,应该使用 bool
进行重载。在第一个位置对于两者来说都是不可行的 foo<-1, 0ul, 1ul, 3ul>();
和foo<+1, 0ul, 1ul, 3ul>();
。我不确定为什么编译器认为后者不明确。根据CWG issue 1407的决议作为非缺陷,从 int
进行转换bool
的模板参数模板参数确实是不允许的,但编译器的行为不符合标准,并且似乎将其视为范围为 0
的整型类型。/1
.
我不知道GCC <8有什么问题。我猜这只是一个错误,它认为过载不明确。
关于c++ - 隐式转换行为不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73129518/