gpt4 book ai didi

c++ - 成对和元组计算嵌套类型

转载 作者:太空宇宙 更新时间:2023-11-04 15:35:12 24 4
gpt4 key购买 nike

我需要计算嵌套对和元组中的类型,并想出了这个片段。但是,如果我使用 gcc 的 declval(),则会出现以下错误:

/usr/include/c++/5.3.0/type_traits:2204:7: 错误:静态断言失败:不得使用 declval()! static_assert(__declval_protector<_Tp>::__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 的却不能?接下来我将尝试使用元模板编程来解决这个问题。

编辑:这是一个修复程序,可以同时使用 gccclang 进行编译:

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在那里所以我们可以找到我们需要的所有重载。使用折叠表达式使这个答案更短,然后我们可以添加:

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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com