考虑下面这段代码:
#include <tuple>
#include <type_traits>
#include <iostream>
template <typename T, typename = void> struct is_tuple_like : std::false_type {};
template <typename T> struct is_tuple_like<T, decltype(std::tuple_size_v<T>, void())> : std::true_type {};
int main()
{
std::cout << is_tuple_like<std::string>::value << '\n';
}
error: incomplete type 'std::tuple_size<...>' used in nested name specifier
在Clang 11.0.1上,无论是使用libstdc++还是libc++,它都能编译并打印出
1
。那么哪个编译器是正确的呢?请注意,Clang打印的是1
而不是0
,这意味着它不会将std::tuple_size<std::string>::value
(即tuple_size_v
的初始化程序)视为软错误,而是选择完全忽略它!从某种意义上讲,这是有道理的,因为如果将tuple_size_v
定义为template <typename T> inline constexpr size_t tuple_size_v = ...
,则类型decltype(tuple_size_v<...>)
不依赖于模板参数,并且始终为size_t
。我想问题归结为是否需要在此处实例化tuple_size_v
的初始化程序,即使这并非绝对必要。我知道可以通过用std::tuple_size<...>::value
替换std::tuple_size_v<...>
来修复它,然后在所有三个编译器上都打印0
。
size_t
或不使用size_t
可以更明确地表述。 - StoryTeller - Unslander Monicastd::size_t
。 - xskxzr