虽然我之前使用过这样的代码,但很明显编译器有足够的信息可以工作,但我真的不明白为什么这会编译:
template <class T, class I>
auto foo(const T& t, I i) {
return std::get<i>(t);
}
int main()
{
std::cerr << foo(std::make_tuple(3,4), std::integral_constant<std::size_t, 0>{});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
实例:http://coliru.stacked-crooked.com/a/fc9cc6b954912bc5.
似乎可以同时使用gcc和clang.的事情是,同时integral_constant具有constexpr转换所存储的整数,constexpr成员函数隐式地把对象本身作为参数,并且因此不能被用在这样的函数constexpr的上下文,除非我们正在呼叫的成员函数的对象本身可以作为被处理constexpr.
这里i是一个传递给的参数foo,因此i绝对不能被视为constexpr.然而,确实如此.一个更简单的例子:
template <class I>
void foo(I i) {
constexpr std::size_t j = i;
}
Run Code Online (Sandbox Code Playgroud)
这也是编译,只要std::integral_constant<std::size_t, 0>{}传递给foo.
我觉得我错过了一些关于constexpr规则的明显内容.无状态类型或其他类型是否有例外?(或者,也许是两个主要编译器中的编译器错误?这个代码似乎适用于clang 5和gcc 7.2).
编辑:答案已经发布,但我认为这还不够.特别是,鉴于最后的定义foo,为什么:
foo(std::integral_constant<std::size_t, …Run Code Online (Sandbox Code Playgroud)