2016-07-15 3 views
3

Я работаю над функцией, которая вызывает предоставленную функцию с переменным числом аргументов. Он компилируется и работает корректно на Visual Studio 2015, но не компилируется на Clang. Я подготовил демонстрацию, которая показывает, что я пытаюсь сделать. Я получаю ошибку в Clang является:Template Parameter Pack Fails on Clang, но не VS 2015

prog.cpp: In function 'int main()': prog.cpp:31:2: error: no matching function for call to 'run(std::vector&, void ()(int&, const int&), const int&)' ); ^prog.cpp:7:6: note: candidate: template void run(std::vector&, const std::function&, mutrArgs ...) void run( ^prog.cpp:7:6: note: template argument deduction/substitution failed: prog.cpp:31:2: note: mismatched types 'const std::function' and 'void ()(int&, const int&)' );

#include <functional> 
#include <iostream> 
#include <vector> 
using namespace std; 

template<int RepeatTimes, class ... mutrArgs> 
void run(
    vector<int>& vec, 
    const function<void(int&, mutrArgs ...)>& mutr, 
    mutrArgs ... args 
) 
{ 
    for (int times{0} ; times < RepeatTimes ; ++times) 
     for (auto& item : vec) 
      mutr(item, args...); 
} 

void adder(int& i, const int& val) 
{ 
    i += val; 
} 

int main() 
{ 
    vector<int> v{0,1,2,3,4,5,6,7,8,9}; 
    const int addValue{4}; 
    run<2, const int&>(
     v, 
     &adder, 
     addValue 
    ); 
    for (auto i : v) 
     cout << i << " "; 
    cout << endl; 
    return 0; 
} 
+0

Вместо использования 'std :: function', также создайте шаблон, как и все [стандартные функции алгоритма] (http://en.cppreference.com/w/cpp/algorithm). –

+0

В не демонстрационной функции требуется принять заданное количество аргументов. – JadziaMD

+2

Если вы используете 'std :: function (& adder)' компилируется. Не уверен, почему это нужно уточнить. Возможно, часть пакета не будет выводимой, но я не уверен в правилах. – NathanOliver

ответ

1

run<2, const int&> просто укажите первый аргумент, но не деактивируйте вычет.

run<2, const int&>(v, &adder, addValue); 

имеет 2 места выводят mutrArgs:

  • addValue ->mutrArgs = { const int& }

  • &adder, который не является std::function и поэтому терпят неудачу.

Принимая адрес функции исправить эту проблему

auto call_run = &run<2, const int&>; 
call_run(v, &adder, addValue); 

Как ни странно, лязг не поддерживает встраиваемое противное использование в НКУ:/

(&run<2, const int&>)(v, &adder, addValue); 

Если вы хотите отключить вывод, вы можете сделать свой шаблон arg не выводимым:

template <typename T> struct identity { using type = T; }; 

template <typename T> using non_deducible_t = typename identity<T>::type; 

А потом

template<int RepeatTimes, class ... mutrArgs> 
void run(
    std::vector<int>& vec, 
    const std::function<void(int&, non_deducible_t<mutrArgs> ...)>& mutr, 
    non_deducible_t<mutrArgs> ... args 
) 

Demo

Даже если в вашем случае простой typename F как предложил Joachim Pileborg кажется лучше.

+0

Чтобы получить окончательную компиляцию на clang, мне нужно было сделать и то, и другое, получить адрес функции и использовать шаблон вывода. – JadziaMD

1

Если вы посмотрите на все standard library algorithm function, по крайней мере, те, принимая «предикат» (вызываемая объект) они принимают этот аргумент в качестве шаблонного типа.

Если вы делаете то же самое он будет строить:

template<int RepeatTimes, typename F, class ... mutrArgs> 
void run(
    vector<int>& vec, 
    F mutr, 
    mutrArgs ... args 
) 
{ 
    ... 
} 

См here for an example of you code. Обратите внимание, что вам не нужно предоставлять все аргументы шаблона, компилятор может их вывести.

+0

Это обходит требуемое использование и, безусловно, будет работать, конечно. – JadziaMD