代码之家  ›  专栏  ›  技术社区  ›  TC.

为每个特定迭代器类型重载

c++
  •  3
  • TC.  · 技术社区  · 16 年前

    我正在使用typedef定义程序中容器的类型,以便可以轻松地在使用普通STL容器和 STXXL 集装箱,沿以下路线:

    typedef stxxl:vector<Data> MyContainer;
    

    typedef std:vector<Data> MyContainer;
    

    一个困难是STXXL提供了 std::for_each , stxxl::for_each 这是为与STXXL容器一起使用而优化的。当mycontainer被定义为 stxxl::vector .

    一个解决办法是定义我自己的 for_each 调用右边的函数 每一个 函数并在我想调用的任何时候使用它 每一个 .

    我目前正在研究的另一个解决方案是过载/专门化 std::foreach 所以它叫 STXXL::福斯每一个 每当使用 stxxl::vector<Data>::(const_)iterator 作为第一个和第二个论点。

    但是我不能让第二个想法起作用。我试过以下方法:

    namespace std
    {
        template <class UnaryFunction>
        UnaryFunction for_each(stxxl:vector<Data>::const_iterator first, 
            stxxl:vector<Data>::const_iterator last, UnaryFunction f)
        {
            stxxl::for_each(first, last, f, 4);
        }
    }
    

    以及非常量迭代器的类似函数。但是他们没有接到电话。

    这个问题的首选解决方案是什么?我怎样才能拿到我的版本 性病:每一个 对于 STXXL:载体 要调用的迭代器?

    更新: 我现在有了第二个想法,正如我所说。问题是我包含了错误的文件(哎呀…)。不过,第一个问题仍然存在:这个问题的首选解决方案是什么?是否可以为每个人重载std::,因为std名称空间不仅仅用于凡人?

    5 回复  |  直到 16 年前
        1
  •  6
  •   Steve Jessop    16 年前

    您可以在std(17.4.3.1)中专门化模板,但不能添加重载。您的定义是一个重载,而不是针对每个模板的标准的专门化,并且在任何情况下函数都不能部分专门化。所以,在名称空间std中放置任何可能满足您需要的定义是未定义的。

    不过,ADL应该让这项工作顺利进行,而不需要这样做。我假设stxxl迭代器在stxxl名称空间中,所以 for_each(first, last, f, 4); 应该打电话 stxxl::for_each . 如果你想要 std::for_each ,调用时完全限定名称。

        2
  •  2
  •   Community Mohan Dere    9 年前

    正如我想说的,你想注入 std 名称空间,正如尼尔指出的,这确实是一个棘手的问题。这个 related thread of std::swap 指出了一些细节,就像现在臭名昭著的 USENET discussion on the subject .

    综上所述,唯一允许您向 性病 如果你能完全专攻的话。所以,你可以写:

    namespace std {
        template <>
        MyFunction for_each(stxxl::vector<Data>::const_iterator first,
                            stxxl::vector<Data>::const_iterator last,
                            MyFunction func)
        {
            return stxxl::for_each(first, last, func);
        }
    }
    

    对于容器和函数的每一个组合,您都很符合规则。不幸的是,部分函数模板专门化在标准的当前体现中不存在。如果你真的很好奇,就花一个晚上来阅读 USENET post . 这真的很有启发性,也有点吓人。如果您只使用一些类型/函数组合,那么您可能可以编写一个漂亮的宏(gasp)来为您实现自动化。

    你可以使用 ADL 如果没有 stxxl 只是从中公开迭代器 性病 使用typedef。我认为这通常是目前首选的解决方案。

    我会加上你自己的包装纸 for_each 它会转发到适当的一个并称之为完成。这不是最优雅的,但它现在可以工作,而且不依赖任何魔法来实现。

        3
  •  1
  •   Alon    16 年前

    std::因为每个函数都是一个公共的、有良好文档记录的算法函数,如果我使用的某个库不断地更改它,我不认为我会像它那样受伤;-。可能我计划的其他部分需要每个人都有好的

    因此,我将使用不破坏此接口的解决方案,并保留std::for_each as i t is。

        4
  •  1
  •   Terry Mahaffey    16 年前

    总结:

    • 不存在函数的部分专门化。仅用特定类型重载该函数
    • 通常禁止将内容放入命名空间std中。
    • 您真正想要的是在您重载的特定迭代器类型(“next to”)的名称空间中为每个类型放置一个重载。这样可以确保ADL找到它。
        5
  •  0
  •   Loki Astari    16 年前

    我不会尝试专门化std::for each()。
    尤其是你想要的是部分专业化。

    相反,我编写的函数使用std::for each(),但对stlxxl有专门化。
    我没有stlxxl,所以我做了一些代码来演示我的意思。

    #include <vector>
    #include <list>
    #include <algorithm>
    #include <iostream>
    
    //
    // Normal version.
    template<typename U,typename T,typename A,template<class I,class A> class C>
    U Ufor_each(C<T,A>& cont,U const& f)
    {
        std::cout << "NORMAL Start" << std::endl;
        return std::for_each(cont.begin(),cont.end(),f);
        return f;
    }
    
    // 
    // Specialized version.
    // You could write a specialized version for stlxxl::vector
    template<typename U,typename T>
    U Ufor_each(std::vector<T>& cont,U const& f)
    {
        std::cout << "Vector Start" << std::endl;
        return std::for_each(cont.begin(),cont.end(),f);
    }
    
    struct X
    {
        void operator()(int data) const
        {
            std::cout << "Item: " << data << std::endl;
        }
    };
    
    int main()
    {
        std::vector<int>    vect;
        std::list<int>      list;
    
        vect.push_back(1);
        list.push_back(4);
    
        X                   x;
        Ufor_each(vect,x);
        Ufor_each(list,x);
    }
    

    我尝试过,但未能使它与迭代器一起工作。