奇怪的模板演绎

时间:2016-06-29 17:28:44

标签: c++ templates

这可能是重复的,但我还没有在其他任何地方找到问题。给出以下代码:

#include <functional>
#include <algorithm>
#include <iostream>
#include <vector>

template<typename container_ty_>
auto where(container_ty_ const& V, std::function<bool(typename container_ty_::value_type const&)>&& comp) 
-> std::vector<std::reference_wrapper<typename container_ty_::value_type>> {
        std::vector<std::reference_wrapper<typename container_ty_::value_type>> cursor;

        for(typename container_ty_::value_type const& VAL : V)
                if(comp(VAL))
                        cursor.push_back(const_cast<typename container_ty_::value_type&>(VAL));

        return cursor;
}

int main(int argc, char** argv) {
        std::vector<int> tVect = {0, 5, 2, 1, 7, 9};

        //Why must std::vector<int> be passed...
        auto vec = where<std::vector<int>>(tVect, [](const int& V) -> bool { return V > 5; });

        std::for_each(vec.begin(), vec.end(), [] (int& v) { std::cout << v++ << std::endl; });
        std::cout << std::endl;
        std::for_each(tVect.begin(), tVect.end(), [](int& v) { std::cout << v << std::endl; });
}

分配vec的行,似乎需要将std::vector<int>传递给它的函数才能编译。如果我现在得到:

  

testing.cpp:20:68:错误:没有匹配函数来调用'where(std::vector<int>&, main(int, char**)::__lambda0)’ auto vec = where(tVect, [](const int& V) -> bool { return V > 5; });

我怀疑这是因为where的第二个参数没有正确推导出模板,任何人都可以向我解释为什么,我似乎处于停滞状态......

此外: 命令行参数:g++ testing.cpp -g -o testing -std=c++11 -Wall

G ++版本:g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4

2 个答案:

答案 0 :(得分:1)

您可能对稍微灵活的版本感兴趣,其中:

  1. 保留源向量中值的常量(取决于向量本身的常量)

  2. 采用任何仿函数,无需std::function

  3. -

    #include <algorithm>
    #include <iostream>
    #include <vector>
    
    template<typename container_ty_, class Comp>
    auto where(container_ty_& V, Comp&& comp)
    {
        using value_type = typename container_ty_::value_type;
        using reference =
        std::conditional_t<
          std::is_const<container_ty_>::value,
            std::reference_wrapper<const value_type>,
            std::reference_wrapper<value_type>
        >;
    
        std::vector<reference> cursor;
    
        for(auto& VAL : V)
            if(comp(VAL))
                cursor.push_back(VAL);
    
        return cursor;
    }
    
    int main(int argc, char** argv) {
        std::vector<int> tVect = {0, 5, 2, 1, 7, 9};
    
        //Why must std::vector<int> be passed...
        auto vec = where(tVect, [](const int& V) -> bool { return V > 5; });
    
        std::for_each(vec.begin(), vec.end(), [] (int& v) { std::cout << v++ << std::endl; });
        std::cout << std::endl;
        std::for_each(tVect.begin(), tVect.end(), [](const int& v) { std::cout << v << std::endl; });
    }
    

答案 1 :(得分:0)

如果我没有明确提供类型参数,我确认我可以用g ++重现问题(Ubuntu 4.8.4-2ubuntu1~14.04.3)4.8.4。

此问题似乎特定于gcc版本4.8。例如,代码使用较新版本的gcc编译,并且在同一平台上,clang ++ - 3.6使用相同的命令行参数编译此代码。