簡體   English   中英

Stl算法作為功能模板

[英]Stl algorithms as function template

我正在嘗試在某些結構上做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

編譯錯誤本身在其他答案中得到了很好的討論。 我提出了使用C ++ 14通用lambda的解決方案:

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

每個人的回答都很好,但讓我再添加一個便條。

為了使您的代碼可以正常工作而無需進行太多更改。這就是必須要做的。

#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

問題是您嘗試將模板作為模板參數傳遞,並希望將其推論-這將不起作用,因為編譯器必須在某個時候開始填充類型: std::find不是typename ,但您需要成為一個!

完全正確。 類型名typename A需要一個類型名。 std::find不是類型。 您可能希望將A a作為常規參數傳遞,然后傳遞std::find的實例化。

似乎您想傳遞要在T實例上執行的函數? 但是您不能使用功能模板來代替預處理器。

find是算法的名稱,而不是類型名。 您需要定義一個用作A的實類型,可能是一個函子,其operator()對其參數執行std::find

建議您先使邏輯在不使用A情況下工作,然后A提取為模板參數。 增量方法通常有助於構建復雜的類或函數模板,並且通常而言,但是損壞的模板代碼的編譯器錯誤尤其令人困惑。

您應該檢查C ++庫中它是如何完成的:

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

如您所見,您必須提供函子類型作為模板參數,並提供函子實例作為函數參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM