2016-09-06 3 views
1

Я пытаюсь реализовать универсальную функцию, которая записывает, как долго выполнялась другая функция.Идеальная пересылка функции шаблона

#include <iostream> 
#include <future> 
#include <thread> 
#include <vector> 
#include <functional> 
#include <numeric> 
#include <memory> 

template<typename Res, typename Func, typename...Args> 
std::pair<Res, double> ftime(Func fun, Args&&... args) 
{ 
    auto start = std::chrono::system_clock::now(); 
    Res res = fun(std::forward<Args>(args)...); 
    std::chrono::duration<double> duration = std::chrono::system_clock::now() - start; 
    return std::make_pair(res, duration.count()); 
} 

int main() 
{ 
    std::vector<int> values (100, 1); 

    auto res = ftime(std::accumulate, values.begin(), values.end(), 0); 
    std::cout << "Sum up " << values.size() << std::endl; 
    std::cout << "Serial sum = " << res.first << " took : " << res.second << std::endl; 
} 

Приведенный выше код не удается скомпилировать со следующей ошибкой:

sum_1000000.cpp: In function ‘int main()’: 
sum_1000000.cpp:22:68: error: no matching function for call to ‘ftime(<unresolved overloaded function type>, std::vector<int>::iterator, std::vector<int>::iterator, int)’ 
    auto res = ftime(std::accumulate, values.begin(), values.end(), 0); 
                    ^
sum_1000000.cpp:10:24: note: candidate: template<class Res, class Func, class ... Args> std::pair<Res, double> ftime(Func, Args&& ...) 
std::pair<Res, double> ftime(Func fun, Args&&... args) 
         ^
sum_1000000.cpp:10:24: note: template argument deduction/substitution failed: 
sum_1000000.cpp:22:68: note: couldn't deduce template parameter ‘Res’ 
    auto res = ftime(std::accumulate, values.begin(), values.end(), 0); 

Насколько я понял, что компилятор не может indentify типы шаблонных функции станд :: acumulate. Что я делаю не так?

Спасибо

+0

Я не вижу, как компилятор может вывести параметр шаблона 'Res'. –

ответ

2

Есть несколько проблем в коде.

Выведите тип возврата функции первого:

template<typename Func, typename...Args> 
auto ftime(Func fun, Args&&... args) -> std::pair<decltype(fun(std::forward<Args>(args)...)), double> 
{ 
    auto start = std::chrono::system_clock::now(); 
    auto res = fun(std::forward<Args>(args)...); 
    std::chrono::duration<double> duration = std::chrono::system_clock::now() - start; 
    return std::make_pair(res, duration.count()); 
} 

std::accumulate не является функцией, а шаблон. Проще всего обернуть вызов в лямбда:

auto res = ftime([&values]() { return std::accumulate(values.begin(), values.end(), 0); }); 
1

компилятор не может вывести Res вашего шаблона, а также он не может вывести paramters шаблон для accumulate.

#include <utility> 
#include <chrono> 
#include <vector> 
#include <numeric> 
#include <iostream> 

template<typename Func, typename...Args> 
auto invoke_timed(Func&& fun, Args&&... args) -> 
    std::pair<decltype(std::forward<Func>(fun)(std::forward<Args>(args)...)), 
    std::chrono::system_clock::duration::rep> 
{ 
    auto start = std::chrono::system_clock::now(); 
    auto res = std::forward<Func>(fun)(std::forward<Args>(args)...); 
    return std::make_pair(res, (std::chrono::system_clock::now() - start).count()); 
} 

int main() 
{ 
    std::vector<int> values(100, 1); 
    auto res = invoke_timed(std::accumulate<std::vector<int>::iterator, int>, 
    values.begin(), values.end(), 0); 

    std::cout << res.first << ", " << res.second << "\n"; 
    return 0; 
} 
+0

Почему вы используете правильную ссылку для 'Func'? –

+0

@GiuseppePes: Нет ссылки на право/rvalue, но ссылка на пересылку, и я использую ее для сохранения категории значений переданного объекта функции, чтобы избежать копирования, так как параметр позволял бы объекты большой функции копироваться так, как вы написали Это. – Pixelchemist

+0

Я вижу. Aren t пересылает ссылку и оценивает ссылку на то же самое? –