简体   繁体   中英

How to get the type of what it depends on from a dependent type in C++

Suppose I define a type iterator inside type Container , so an object of this type would be Container::iterator . How can I get the type it depends on, which is 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());

This is a generalized problem from what I found here: Obtain container type from (its) iterator type in C++ (STL) but since it's 10 years old now, I bet there may be some magic solutions.

EDIT: I generalized the problem to a dependent type, not particular to container, where as some may suggest std::vector<T>::iterator implemented as a pointer

Suppose there are some types, all defines a common typename inside

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: Why is Thing here can't be deduced, any reason for this?

If you want to deduct the outer container type from the inner iterator type, you have to define the container type within the iterator:

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

Then you have to pass the iterator type to the getContainer function, instead of the container type:

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

This way you can resolve the issue of providing the requested container to the template:

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

Why is Thing here can't be deduced, any reason for this?

Because this belongs to non-deduced context .

(emphasis mine)

In the following cases, the types, templates, and non-type values that are used to compose P do not participate in template argument deduction, but instead use the template arguments that were either deduced elsewhere or explicitly specified. If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.

  1. The nested-name-specifier (everything to the left of the scope resolution operator :: ) of a type that was specified using a qualified-id:

For example,

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

Both std::vector<int>::iterator and my_int_vector::iterator refer to the same type. Then

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 ?

Another sample might be

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM