[英]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.