2016-07-15 5 views
3

Ich arbeite an einer Funktion, die eine angegebene Funktion mit einer variablen Anzahl von Argumenten aufruft. Es kompiliert und funktioniert ordnungsgemäß in Visual Studio 2015, kann jedoch nicht mit Clang kompiliert werden. Ich habe eine Demonstration vorbereitet, die zeigt, was ich versuche zu tun. Der Fehler, den ich in Clang bekommen ist:Template Parameter Pack schlägt auf Clang, aber nicht 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

Anstatt "std :: function" zu verwenden, muss auch der Typ eine Vorlage sein, wie alle [standard algorithm functions] (http://en.cppreference.com/w/cpp/algorithm). –

+0

In der Nichtdemonstrationsfunktion ist es erforderlich, eine bestimmte Anzahl von Argumenten zu verwenden. – JadziaMD

+2

Wenn Sie 'std :: function (& addierer)' verwenden, kompiliert es. Nicht sicher, warum es jedoch angegeben werden muss. Könnte damit zu tun haben, dass der Packteil nicht ableitbar ist, aber ich bin mir der Regeln nicht sicher. – NathanOliver

Antwort

1

run<2, const int&> Geben Sie nur das erste Argument an, aber deaktivieren Sie den Abzug nicht.

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

hat 2 Plätze mutrArgs ableiten:

  • addValue ->mutrArgs = { const int& }

  • &adder, die kein std::function ist und so scheitern.

Unter Adresse der Funktion

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

Seltsam, dieses Problem zu beheben, Klirren unterstützt nicht die inlined Nutzung im Gegensatz zu gcc:/

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

Wenn Sie Abzug deaktivieren möchten, Sie können Ihre Vorlage Arg nicht nachvollziehbar machen:

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

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

Und dann

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

Auch in Ihrem Fall, wenn eine einfache typename F wie von Joachim Pileborg besser scheint.

+0

Um es richtig zu kompilieren auf clang zu bekommen, musste ich beides machen, die Funktionsadresse holen und die deduzierende Vorlage verwenden. – JadziaMD

1

Wenn Sie überhaupt standard library algorithm function aussehen, zumindest die, die ein „Prädikat“ (ein aufrufbare Objekt) nehmen sie dieses Argument als Templat-Typen nehmen.

Wenn Sie das gleiche tun wird es bauen:

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

here for an example of you code See. Beachten Sie, dass Sie nicht alle Vorlagenargumente angeben müssen, da der Compiler sie ableiten kann.

+0

Dies umgeht die benötigte Verwendung und würde natürlich sicher funktionieren. – JadziaMD

Verwandte Themen