我经常在大型代码库中遇到不遵循 typedef 标准约定的代码,例如ThisType
而不是this_type
.
编写我不再依赖的通用代码 this_type
意味着我必须为没有 this_type
的每种类型提供一些脚手架代码.
我想都是this_type
和ThisType
可以定义。然而,在大型代码库中,这会增加额外的噪音,并且是审查需要定期检查的内容。
有没有办法将其包装在 type_trait
中这样我就可以写一些类似的东西:this_type<SomeType>::value_type
或其他一些通用解决方案?
最佳答案
也许可以用更简单的方式来完成......无论如何,我建议使用标签调度/SFINAE 解决方案。
首先,一个简单的递归tag
结构
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>);
一个用于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> );
}
关于c++ - 处理通用代码中不一致的 typedef,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71340563/