我需要计算嵌套对和元组中的类型,并提出了此代码段。但是,如果我使用gcc的declval()
,则会发生以下错误:
/usr/include/c++/5.3.0/type_traits:2204:7:错误:静态断言失败:不得使用declval()!
static_assert(__ declval_protector :: __ stop,
struct swallow
{
template <typename ...T>
explicit swallow(T&& ...) noexcept
{
}
};
template <typename C>
constexpr inline decltype(auto) declval() noexcept
{
return ::std::move(*static_cast<C*>(nullptr));
}
template <typename T>
constexpr inline auto count_types(T const&) noexcept
{
return 1;
}
template <typename ...A>
constexpr inline auto count_types(::std::pair<A...> const&) noexcept
{
int r{};
swallow{(r += count_types(declval<A>()))...};
return r;
}
template <typename ...A>
constexpr inline auto count_types(::std::tuple<A...> const&) noexcept
{
int r{};
swallow{(r += count_types(declval<A>()))...};
return r;
}
int main()
{
::std::cout << count_types(declval<::std::tuple<int, int, ::std::pair<int, ::std::pair<int, int>>>>());
return 0;
}
我的问题是为什么为什么我的
declval
实现正确工作,而gcc却不能正常工作?接下来,我将尝试使用元模板编程来解决该问题。编辑:这是一个修复程序,可以同时使用
gcc
和clang
进行编译:struct swallow
{
template <typename ...T>
constexpr explicit swallow(T&& ...) noexcept
{
}
};
template <typename C>
constexpr inline decltype(auto) declval() noexcept
{
return static_cast<typename std::remove_reference<C>::type&&>(*static_cast<C*>(nullptr));
}
template <typename T>
constexpr inline auto count_types(T const&) noexcept
{
return 1;
}
template <typename ...A>
constexpr inline auto count_types(::std::pair<A...> const&) noexcept
{
int r{};
swallow{(r += count_types(declval<A>()))...};
return r;
}
template <typename ...A>
constexpr inline auto count_types(::std::tuple<A...> const&) noexcept
{
int r{};
swallow{(r += count_types(declval<A>()))...};
return r;
}
int main()
{
::std::cout << ::std::integral_constant<int, count_types(declval<::std::tuple<int, int, ::std::pair<int, ::std::pair<int, int>>>>())>{};
return 0;
}
最佳答案
std::declval
专用于编译时逻辑。从[declval]定义为:
template <class T>
add_rvalue_reference_t<T> declval() noexcept; // as unevaluated operand
该功能没有主体。它只是在那里给你一个类型。您无法对其执行运行时操作。那不是它的目的。
declval
的实现涉及在运行时显式取消引用空指针。这只是对declval
的用途及其用法的误解。此外,您的declval
实现不支持左值引用(例如,我可以std::declval<Foo&>()
给我一个左值引用,由于要使用指向引用的指针,所以your_declval<Foo&>()
格式不正确)。编写类似内容的方法将基于类型。您仍然可以编写一个使用
std::tuple<A...>
并返回嵌套类型数量的函数-只是不能是运行时操作,它应该将结果编码为类型。也就是说,我们从以下内容开始:struct adl_tag {};
template <class T>
inline auto count_types_impl(adl_tag, T const&)
-> std::integral_constant<int, 1>;
template <class T>
using count_types = decltype(count_types_impl(adl_tag{}, std::declval<T>()));
然后只需为我们希望支持的其他类型的
count_types_impl()
添加其他重载即可。 adl_tag
在那里,因此我们可以找到所需的所有重载。使用fold-expressions缩短答案,然后可以添加:template <class... A>
inline auto count_types_impl(adl_tag , std::tuple<A...> const&)
-> std::integral_constant<int, (count_types<A>::value + ...)>;
template <class A, class B>
inline auto count_types_impl(adl_tag , std::pair<A,B> const&)
-> std::integral_constant<int, (count_types<A>::value + count_types<B>::value)>;
以便:
std::cout << count_types<std::tuple<int, std::pair<int,int>>>::value; // prints 3
请注意,绝不会评估任何内容。这些功能都没有身体!
关于c++ - 成对和元组计数嵌套类型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35817668/