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

问题描述

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

然而,并非所有容器(或其他模板化类)都定义了这样的 value_type,尤其是较旧的容器。 即使没有它,是否有可能到达包含的 T

我知道有一些技巧,比如“如果它是一个迭代器,那么 .begin() 应该返回那个类型的值”,但这对我们没有帮助,例如编写一个概念要求,检查类的 .begin() 是否确实符合迭代器的要求。

解决方法

这是一个类似于 Quimby's solution 的解决方案,但使用了部分模板特化:

readiness

这是从 Quimby 的解决方案中借用的 demo

,

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

#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 的可能解决方案相反。