【问题标题】:How to get the type of what it depends on from a dependent type in C++如何从 C++ 中的依赖类型中获取它所依赖的类型
【发布时间】:2020-07-15 06:43:49
【问题描述】:

假设我在类型Container 中定义了一个类型iterator,那么这个类型的对象就是Container::iterator。如何获取它所依赖的类型,即Container?

struct Container
{
    struct iterator {};
};

template<typename Cont>
auto getContainer(typename Cont::iterator&& iter)
{
    return Cont{}; //return an empty container from the iterator, but type of Cont canNOT be deduced :(
}

//example
std::vector<int> v;
auto v2=getContainer(v.begin());

这是我在这里发现的一个普遍问题:Obtain container type from (its) iterator type in C++ (STL) 但既然它已经 10 岁了,我敢打赌可能会有一些神奇的解决方案。

编辑:我将问题概括为依赖类型,而不是特定于容器,其中有些人可能会建议 std::vector&lt;T&gt;::iterator 实现为指针

假设有一些类型,都在里面定义了一个共同的typename

struct Something { struct SomeInnerType{}; };
struct SomeOtherThing { struct SomeInnerType{}; };

template<typename Thing>
auto getDepend(typename Thing::SomeInnerType&& obj)
{                       //^ why this can't be deduced (EDIT2)
    return Thing{};
}

EDIT2:为什么Thing这里不能推导出来,有什么原因吗?

【问题讨论】:

  • “get”是什么意思?类型信息应该有什么形状?你想怎么用?
  • 不,和 10 年前一样。
  • 我认为这通常是不可能的。例如,连续容器的迭代器,例如std::vector,可以简单地实现为指针。如何从普通指针中“提取”有关容器的信息?
  • Works for me。 ???你怎么称呼getContainer?
  • @Carsten 这显然不是我使用getContainer 的目的,因为您明确专门化了该类型。我要自动扣款解决方案

标签: c++ templates


【解决方案1】:

如果要从内部迭代器类型中减去外部容器类型,则必须在迭代器内定义容器类型:

struct Container {
public:
    struct iterator {
    public:
        using container_type = Container;
    };
};

那么你必须将迭代器类型传递给getContainer函数,而不是容器类型:

template <typename TIter>
TIter::container_type getContainer(TIter&& iter) {
    return typename TIter::container_type {};
}

这样可以解决向模板提供请求容器的问题:

int main() 
{
    auto it = Container::iterator();
    auto c = getContainer(std::move(it));
}

【讨论】:

  • 赞成,是的,这解决了问题,但你能解释一下我的EDIT2,这种依赖模板扣除限制的原因
  • 当然!当您显式调用该函数时,您会这样写:getContainer&lt;Container::iterator&gt;(std::move(it));。但是,此参数可以从参数列表中隐式扣除,因此您可以省略它。在您的示例中,getContainer 的定义方式是它需要知道容器类型以从中扣除迭代器 - 但是,如 cmets 中所述 - 提供容器使函数的目的失败,即扣除容器从迭代器。为此,您需要提供迭代器并将其声明为容器。
【解决方案2】:

为什么Thing这里推不出来,有什么原因吗?

因为这属于non-deduced context。

(强调我的)

在以下情况下,类型、模板和非类型值 用于撰写P 不参与模板参数 推论,而是使用模板参数 在别处推断或明确指定。 如果模板参数是 仅在非推导上下文中使用且未明确指定, 模板参数推导失败。

  1. nested-name-specifier(范围左侧的所有内容 分辨率运算符::) 使用指定的类型 合格 ID:

例如,

struct my_int_vector {
    using iterator = std::vector<int>::iterator;
};

std::vector&lt;int&gt;::iterator 和 my_int_vector::iterator 指的是同一个类型。那么

std::vector<int> v;
auto v2=getContainer(v.begin());                 // What should Thing be deduced as ?
auto v3=getContainer(my_int_vector::iterator{}); // What should Thing be deduced as ?

另一个样本可能是

struct my_int_vector {
    using iterator = int*;
};
auto v3=getContainer(nullptr); // How could Thing be deduced as my_int_vector based on any information?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-21
    • 1970-01-01
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 2019-03-12
    • 1970-01-01
    相关资源
    最近更新 更多