简体   繁体   中英

C++ Passing templated functions to function

I need to pass a templated function to a function.

Until now I haven't found any great advices on google. This is what I tried:

#include <iostream>
#include <sstream>
using namespace std;

struct event {
  bool signal;
};

template<typename T>
void out_stream(T &stream, event &evt) {
  stream << evt.signal;
}

template <typename F>
void doOperation(F f)
{
  event test;
  test.signal = 0;
  stringstream ss;

  f(ss, test);
}

int main() {

  doOperation(out_stream);

  return 0;
}

And that's the error the compiler gives me:

main.cc:27:3: error: no matching function for call to 'doOperation'
  doOperation(out_stream);
  ^~~~~~~~~~~
main.cc:16:6: note: candidate template ignored: couldn't infer template argument 'F'
void doOperation(F f)
     ^
1 error generated.

Some (I hope) useful information about my g++ compiler setup:

  • Apple clang version 13.0.0 (clang-1300.0.29.30)
  • Target: x86_64-apple-darwin20.6.0
  • Thread model: posix

Thank you in advance:)

For this particular case, you could help the compiler deduce T by calling doOperation with out_stream<std::stringstream> .

Also, within doOperation , you need to use f instead of F .

[Demo]

#include <iomanip>  // boolalpha
#include <iostream>  // cout
#include <sstream>  // stringstream

struct event {
    bool signal{};
};

template<typename T>
void out_stream(T& stream, const event& evt) {
    stream << std::boolalpha << evt.signal;
}

template <typename F>
void doOperation(F&& f) {
    std::stringstream ss{};
    f(ss, event{true});
    std::cout << ss.str() << "\n";
}

int main() {
    doOperation(out_stream<std::stringstream>);
}

// Outputs:
//
//   true

As suggested in the comments though, other options you have instead of passing an instantiation of a function template are:

  1. Change out_stream to accept an std::ostream& .
  2. Pass a generic lambda that just calls the instantiation of the function template.

[Demo]

#include <iomanip>  // boolalpha
#include <iostream>  // cout
#include <sstream>  // stringstream

struct event {
    bool signal{};
};

void out_stream1(std::ostream& stream, const event& evt) {
    stream << std::boolalpha << evt.signal;
}

template <typename T>
void out_stream2(T& stream, const event& evt) {
    stream << std::boolalpha << evt.signal;
}

template <typename F>
void doOperation(F&& f) {
    std::stringstream ss{};
    f(ss, event{true});
    std::cout << ss.str() << "\n";
}

int main() {
    doOperation(out_stream1);
    doOperation([](auto& stream, const auto& evt) { out_stream2(stream, evt); });
}

// Outputs:
//
//   true
//   true

Notice also there are no templated functions , but function templates . out_stream is a function template. It needs to be instantiated with a given type, eg out_stream<std::stringstream> , to become a function. That's why the call doOperation(out_stream); doesn't compile; because the compiler is unable to deduce the type of the function template you want to use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM