Toppest.Of.Kek
Toppest.Of.Kek

Reputation: 131

Strange Template Deduction

This may be a duplicate, but I haven't found the problem anywhere else yet. Given the following code:

#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; });
}

The line where vec is being assigned, the function where seems to need to have std::vector<int> passed into it in order to compile. if now i get:

testing.cpp:20:68: error: no matching function for call to ‘where(std::vector<int>&, main(int, char**)::__lambda0)’ auto vec = where(tVect, [](const int& V) -> bool { return V > 5; });

I suspect this is because the template is not being deduced correctly for the second argument of where could anyone explain to me why, i seem to be at a standstill...

Also: Command line args: g++ testing.cpp -g -o testing -std=c++11 -Wall

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

Upvotes: 3

Views: 91

Answers (2)

Richard Hodges
Richard Hodges

Reputation: 69882

You may be interested in a slightly more flexible version, which:

  1. preserves constness of the values in the source vector (depending on the constness of the vector itself)

  2. Takes any functor, no need for a std::function

-

#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; });
}

Upvotes: 1

trygub
trygub

Reputation: 87

If I do not provide the type parameter explicitly I confirm I can reproduce the problem with g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4.

This problem seems to be specific to gcc version 4.8. E.g., the code compiles with newer versions of gcc, and, on the same platform, clang++-3.6 compiles this code with the same command line parameters.

Upvotes: 0

Related Questions