<T>如果没有提供容器::value_type,如何获得C++容器的T?



容器模板包含value_type类型定义是相当常见的。这使得创建其他模板代码(最近的概念)变得容易,如果只给定Container而不给定Container<T>,则能够提取T

然而,并不是所有的容器(或其他模板类)都定义了这样的value_type,尤其是旧的容器。是否有可能得到包含T

,即使没有它?我知道有一些技巧,比如"如果它是一个迭代器,那么.begin()应该返回该类型的值",但这并不能帮助我们编写一个概念要求来检查一个类的.begin()是否确实遵循迭代器的要求。

这里有一个与Quimby的解决方案类似的解决方案,但使用了部分模板特化:

template<typename...>
struct inner_type_impl;
template<template<typename...> typename C, typename T, typename...Args>
struct inner_type_impl<C<T,Args...>>
{
using type = T;
};
template<typename T>
using inner_type = typename inner_type_impl<T>::type;

这是一个借鉴Quimby的解决方案的演示。

可以使用类模板特化或模板参数推导来实现这一点。只要内部类型是第一个模板参数,下面的代码就可以工作:

#include <type_traits>
// Consider the first template argument to be the inner type.
template<template<typename,typename...>class C,typename T,typename...Args>
auto inner_type_impl(const C<T,Args...>* v)->T*{return nullptr;};
template<typename T>
using inner_type = std::remove_pointer_t<decltype(inner_type_impl((T*)nullptr))>;

template<typename T>
struct Container;
// Will still deduce T
template<typename T,typename...Extras>
struct ContainerExtraParams;
static_assert(std::is_same_v<int,inner_type<Container<int>>>);
static_assert(std::is_same_v<int,inner_type<ContainerExtraParams<int,double,float>>>);

我使用指针使代码在求值的上下文中也有效。与std::declval的可能解决方案相反。

最新更新