处理通用代码中不一致的 typedef

发布于 2025-01-11 08:19:52 字数 432 浏览 0 评论 0原文

我经常在大型代码库中遇到不遵循 typedef 标准约定的代码,例如 ThisType 而不是 this_type

编写不再依赖 this_type 的通用代码意味着我必须为没有 this_type 的每种类型提供一些脚手架代码。

我想 this_typeThisType 都可以定义。然而,在大型代码库中,这会增加额外的噪音,并且是审查需要定期检查的内容。

有没有办法将其包装在 type_trait 中,以便我可以按照以下方式编写一些内容: this_type::value_type OR其他一些通用解决方案?

I routinely come across code in large codebases that do not follow the standard convention for typedefs e.g. ThisType instead of this_type.

Writing generic code where I can no longer rely on this_type means I have to provide some scaffolding code for each type that does not have this_type.

I suppose both this_type and ThisType can be defined. However, in a large codebase that adds extra noise and is something that reviews will need to routinely check.

Is there a way to wrap it in a type_trait such that I can write something along the lines of: this_type<SomeType>::value_type OR some other generic solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

玩套路吗 2025-01-18 08:19:52

也许可以用更简单的方式来完成......无论如何,我提出了标签调度/SFINAE 解决方案。

首先,一个简单的递归 tag 结构,

template <std::size_t N>
struct tag : public tag<N-1u>
{ };

template <>
struct tag<0u>
{ };

以避免在定义了多个可能的类型名称的情况下出现歧义。

然后为您想要从可能的类型中提取的每种类型提供一个模板函数(仅声明);一个用于 type

template <typename T, std::void_t<typename T::type>* = nullptr>
typename T::type getType (tag<0u>);

一个用于 this_type

template <typename T, std::void_t<typename T::this_type>* = nullptr>
typename T::this_type getType (tag<1u>);

一个用于 ThisType

template <typename T, std::void_t<typename T::ThisType>* = nullptr>
typename T::ThisType getType (tag<2u>);

一个(有点傻)用于 MySillyTypeName

template <typename T, std::void_t<typename T::MySillyTypeName>* = nullptr>
typename T::MySillyTypeName getType (tag<3u>);

请注意标签的数量不同:这避免了可能的歧义并给出了名称的优先顺序。

现在是一个简单的结构,它使用 getType() 来提取所需的类型

template <typename T, typename U = decltype(getType<T>(tag<100u>()))>
struct GetType { using type = U; };

以下是完整的编译 C++17 示例

#include <type_traits>

template <std::size_t N>
struct tag : public tag<N-1u>
{ };

template <>
struct tag<0u>
{ };

template <typename T, std::void_t<typename T::type>* = nullptr>
typename T::type getType (tag<0u>);

template <typename T, std::void_t<typename T::this_type>* = nullptr>
typename T::this_type getType (tag<1u>);

template <typename T, std::void_t<typename T::ThisType>* = nullptr>
typename T::ThisType getType (tag<2u>);

template <typename T, std::void_t<typename T::MySillyTypeName>* = nullptr>
typename T::MySillyTypeName getType (tag<3u>);

template <typename T, typename U = decltype(getType<T>(tag<100u>()))>
struct GetType { using type = U; };

struct foo1 { using type = short; };
struct foo2 { using this_type = int; };
struct foo3 { using ThisType = long; };
struct foo4 { using MySillyTypeName = long long; };

int main()
{
  static_assert( std::is_same_v<short,     GetType<foo1>::type> );
  static_assert( std::is_same_v<int,       GetType<foo2>::type> );
  static_assert( std::is_same_v<long,      GetType<foo3>::type> );
  static_assert( std::is_same_v<long long, GetType<foo4>::type> );
}

Maybe can be done in a simpler way... anyway, I propose a tag dispatching / SFINAE solution.

First of all, a simple recursive tag struct

template <std::size_t N>
struct tag : public tag<N-1u>
{ };

template <>
struct tag<0u>
{ };

to avoid ambiguities in cases more that one of the possible type names are defined.

Then a template function (only declared) for every type you want extract from the possible types; one for type

template <typename T, std::void_t<typename T::type>* = nullptr>
typename T::type getType (tag<0u>);

one for this_type

template <typename T, std::void_t<typename T::this_type>* = nullptr>
typename T::this_type getType (tag<1u>);

one for ThisType

template <typename T, std::void_t<typename T::ThisType>* = nullptr>
typename T::ThisType getType (tag<2u>);

and one (to be a little silly) for MySillyTypeName

template <typename T, std::void_t<typename T::MySillyTypeName>* = nullptr>
typename T::MySillyTypeName getType (tag<3u>);

Observe that the number of the tag are differents: this avoid the possible ambiguity and give a priority order for the names.

Now a trivial struct that uses getType() to extract the required type

template <typename T, typename U = decltype(getType<T>(tag<100u>()))>
struct GetType { using type = U; };

The following is a full compiling C++17 example

#include <type_traits>

template <std::size_t N>
struct tag : public tag<N-1u>
{ };

template <>
struct tag<0u>
{ };

template <typename T, std::void_t<typename T::type>* = nullptr>
typename T::type getType (tag<0u>);

template <typename T, std::void_t<typename T::this_type>* = nullptr>
typename T::this_type getType (tag<1u>);

template <typename T, std::void_t<typename T::ThisType>* = nullptr>
typename T::ThisType getType (tag<2u>);

template <typename T, std::void_t<typename T::MySillyTypeName>* = nullptr>
typename T::MySillyTypeName getType (tag<3u>);

template <typename T, typename U = decltype(getType<T>(tag<100u>()))>
struct GetType { using type = U; };

struct foo1 { using type = short; };
struct foo2 { using this_type = int; };
struct foo3 { using ThisType = long; };
struct foo4 { using MySillyTypeName = long long; };

int main()
{
  static_assert( std::is_same_v<short,     GetType<foo1>::type> );
  static_assert( std::is_same_v<int,       GetType<foo2>::type> );
  static_assert( std::is_same_v<long,      GetType<foo3>::type> );
  static_assert( std::is_same_v<long long, GetType<foo4>::type> );
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文