Skip to content

Instantly share code, notes, and snippets.

@maraigue
Last active January 1, 2016 08:18
Show Gist options
  • Select an option

  • Save maraigue/8116989 to your computer and use it in GitHub Desktop.

Select an option

Save maraigue/8116989 to your computer and use it in GitHub Desktop.
Storing functional objects in C++ (pointer for function, functor and lambda) in std::function or template class
[Compile]
See Makefile
[Run]
(Counts the number of characters for each line)
./sample-std-function data.txt
./sample-template data.txt
the
quick
brown
fox
jumps
over
the
lazy
dog
CXXFLAGS = -std=c++11
default:
# make sample-{std-function,template}
sample-std-function: sample-std-function.cpp sample-std-function.hpp
$(CXX) $(CXXFLAGS) $< -o $@
sample-template: sample-template.cpp sample-template.hpp
$(CXX) $(CXXFLAGS) $< -o $@
clean:
rm -f sample-std-function sample-template
#include "sample-std-function.hpp"
#include <iostream>
int length_printer(const std::string & buf){
std::cout << buf.length() << std::endl;
return buf.length();
}
struct LengthPrinter{
int operator()(const std::string & buf) const{
std::cout << buf.length() << std::endl;
return buf.length();
}
};
int main(int argc, char *argv[]){
if(argc == 2){
std::cout << "-- void length_printer(const std::string &)" << std::endl;
StringProcessorF sp1(length_printer);
sp1.process_file(argv[1]);
std::cout << "-- void LengthPrinter::operator()(const std::string &)" << std::endl;
LengthPrinter lenprint_functor;
StringProcessorF sp2(lenprint_functor);
sp2.process_file(argv[1]);
std::cout << "-- [](const std::string & buf){ ... }" << std::endl;
StringProcessorF sp3([](const std::string & buf){ std::cout << buf.length() << std::endl; return buf.length(); });
sp3.process_file(argv[1]);
}else{
std::cerr << "Usage: " << argv[0] << " FILENAME" << std::endl;
}
}
#include <fstream>
#include <string>
#include <functional>
class StringProcessorF{
public:
typedef std::function<int(const std::string &)> func_type;
private:
const func_type func_;
public:
StringProcessorF(const func_type & func) : func_(func) {}
int process(const std::string & buf) const{
return func_(buf);
}
int process_file(const char * filename) const{
std::ifstream ifs(filename);
if(!ifs) return 0;
std::string buf;
int sum = 0;
for(;;){
std::getline(ifs, buf);
if(ifs.eof()) break;
sum += func_(buf);
}
return sum;
}
};
#include "sample-template.hpp"
#include <iostream>
int length_printer(const std::string & buf){
std::cout << buf.length() << std::endl;
return buf.length();
}
struct LengthPrinter{
int operator()(const std::string & buf) const{
std::cout << buf.length() << std::endl;
return buf.length();
}
};
int main(int argc, char *argv[]){
if(argc == 2){
std::cout << "-- void length_printer(const std::string &)" << std::endl;
auto sp1 = make_string_processor(length_printer);
sp1.process_file(argv[1]);
std::cout << "-- void LengthPrinter::operator()(const std::string &)" << std::endl;
auto sp2 = make_string_processor(LengthPrinter());
sp2.process_file(argv[1]);
std::cout << "-- [](const std::string & buf){ ... }" << std::endl;
auto sp3 = make_string_processor([](const std::string & buf){ std::cout << buf.length() << std::endl; return buf.length(); });
sp3.process_file(argv[1]);
}else{
std::cerr << "Usage: " << argv[0] << " FILENAME" << std::endl;
}
}
#include <fstream>
#include <string>
// Assume FUNCTYPE has the form 'int F(const std::string &)'
template <class FUNCTYPE>
class StringProcessorT{
private:
const FUNCTYPE & func_;
public:
StringProcessorT(const FUNCTYPE & func) : func_(func) {}
int process(const std::string & buf) const{
return func_(buf);
}
int process_file(const char * filename) const{
std::ifstream ifs(filename);
if(!ifs) return 0;
std::string buf;
int sum = 0;
for(;;){
std::getline(ifs, buf);
if(ifs.eof()) break;
sum += func_(buf);
}
return sum;
}
};
template <class FUNCTYPE>
StringProcessorT<FUNCTYPE> make_string_processor(const FUNCTYPE & func){
return StringProcessorT<FUNCTYPE>(func);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment