Stl算法作为函数模板

时间:2015-06-25 12:32:48

标签: c++ templates

我正在尝试在某些结构上对stl算法进行基准测试:

using namespace std;

template<typename A, typename T>
void test(){
    T c(1000);
    A(c.begin(), c.end(), true);

}
int main(){
    test<find,vector<bool>>();
}

但我得到template argument deduction/substitution failed

6 个答案:

答案 0 :(得分:3)

编译错误本身在其他答案中得到了很好的讨论。我提出了一个使用C ++ 14通用lambdas的解决方案:

template<typename Container, typename Algorithm>
void test(Algorithm algo = Algorithm()){
    Container c(1000);
    algo(c.begin(), c.end(), true);
}

int main(){
    auto find_proxy = [](auto ... args){ return std::find(args...); };
    test<std::vector<bool>>(find_proxy);
}

答案 1 :(得分:1)

每个人的回答都很好,但是让我再补充一点。

让代码正常工作而不会发生太大变化..这就是必须要发生的事情。

#include <vector>
#include <algorithm>

template< typename SearchFunctionType, typename ContainerType >
void test( SearchFunctionType fSearch, const ContainerType& container){
    fSearch(container.begin(), container.end(), true);
}

int main(){
    std::vector<bool> v(1000);
    test(std::find<std::vector<bool>::const_iterator, bool>, v);
}

std :: find不是每个人都指出的类型。 std :: find是一个函数。您可以将其作为函数指针传递。然后看,std :: find又是模板函数,编译器也不知道std :: find会有哪些模板参数。这就是为什么你不只是传递std :: find。相反,

std::find<std::vector<bool>::const_iterator, bool>.

编辑:

#include <algorithm>
#include <vector>


template < typename ContainerType
         , typename ContainerType::const_iterator (*fpSearchFunction) (typename ContainerType::const_iterator, typename ContainerType::const_iterator, const typename ContainerType::value_type&) >
void test(const ContainerType& c, const typename ContainerType::value_type& value)
{
    fpSearchFunction(c.begin(), c.end(), value);
}


int main()
{
    std::vector<bool> v(1000);
    test< std::vector<bool>, std::find<std::vector<bool>::const_iterator, bool> >(v, true);
}

这适用于VisualC。是。整数类型或函数指针也可以是模板参数。我打赌有比这更好的方法。

编辑2:

虽然我不明白为什么把它加以寺庙化比仅仅硬编码更好,但如果我确实做了一些复杂的话,我就会这样做。

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

template <typename ContainerType>
class Benchmark
{
public:
    typedef typename ContainerType::const_iterator  ConstIteratorType;
    typedef typename ContainerType::value_type      ValueType;
    typedef std::function < ConstIteratorType(ConstIteratorType, ConstIteratorType, const ValueType&) >
        SearchFunctionType;
    typedef std::chrono::high_resolution_clock      ClockType;

    void TestAll(const ContainerType& container, const ValueType& serachVal)
    {
        for (std::size_t i = 0; i < m_functions.size(); ++i)
        {




            ClockType::time_point begin = ClockType::now();
            m_functions[i](container.begin(), container.end(), serachVal);
            ClockType::duration duration = ClockType::now() - begin;
            std::cout << i << " : " << duration.count() << std::endl;
        }
    }

    void PushBack(SearchFunctionType fSearch)
    {
        m_functions.push_back(fSearch);
    }
private:
    std::vector<SearchFunctionType> m_functions;
};

int main(){

    typedef Benchmark<std::vector<bool>> BenchmarkType;
    BenchmarkType benchmark;
    benchmark.PushBack(std::find<BenchmarkType::ConstIteratorType, BenchmarkType::ValueType>);
    benchmark.PushBack([](BenchmarkType::ConstIteratorType begin, BenchmarkType::ConstIteratorType end, const BenchmarkType::ValueType& v)
    {
        BenchmarkType::ConstIteratorType iter;
        do
        {
            iter = begin + std::rand() % (end - begin);
            if (*iter == v)
                return iter;
        } while (iter != end);
        return end;
    });
    struct BinarySearch
    {
        BenchmarkType::ConstIteratorType operator()(BenchmarkType::ConstIteratorType begin, BenchmarkType::ConstIteratorType end, const BenchmarkType::ValueType& v)
        {


            return std::lower_bound(begin, end, v);
        }
    };
    benchmark.PushBack(BinarySearch());

    std::vector<bool> c;
    c.assign(10000, false);
    c.back() = true;

    benchmark.TestAll(c, true);

}

输出:

0 : 100005
1 : 300017
2 : 0

答案 2 :(得分:0)

问题是你试图将模板作为模板参数传递,并希望它被推断 - 这不会起作用,因为编译器必须在某个时刻开始填充类型:{{1 }}不是std::find,但你需要它是一个!

答案 3 :(得分:0)

非常正确。 valgrind需要类型名称。 typename A不是一种类型。您可能希望将std::find作为常规参数传递,然后传递A a的实例化。

答案 4 :(得分:0)

好像你想传递一个要在function addSelectBox(){ var parentDiv = document.getElementById ("main"); var selectElement = '<select>'; for (var i=0;i < 6000;i++) { selectElement+= '<option value="'+i+'">---- ' + i+'</option>'; } selectElement += '</select>'; parentDiv.innerHTML+=selectElement; } 的实例上执行的函数?但是您不能使用函数模板来替换预处理器。

T是算法的名称,而不是类型名称。您需要定义要用作find的真实类型,也许是A在其参数上执行operator()的仿函数。

建议您首先使用std::find使逻辑工作,然后提取A作为模板参数。增量方法通常有助于构建复杂的类或函数模板,并且通常,但是破坏的模板代码的编译器错误可能尤其令人困惑。

答案 5 :(得分:0)

您应该检查它在C ++库中的完成情况:

template< class InputIt, class UnaryPredicate >
typename iterator_traits<InputIt>::difference_type
    count_if( InputIt first, InputIt last, UnaryPredicate p );

如您所见,您必须将functor类型作为模板参数和functor实例作为函数参数提供。