Skip to content

Instantly share code, notes, and snippets.

@groundwater
Created July 26, 2016 06:45
Show Gist options
  • Save groundwater/bafd8d8dfc3b44a4bdebbd506977c2cc to your computer and use it in GitHub Desktop.
Save groundwater/bafd8d8dfc3b44a4bdebbd506977c2cc to your computer and use it in GitHub Desktop.
c++ dependency injection via templates
#import <iostream>
// A simple container class for holding results
class Item {
using str = std::string;
private:
str _item;
public:
Item(str k): _item {k} {}
const str value() const {
return _item;
}
};
// Utility to enable "std::cout << item"
std::ostream & operator<<(std::ostream &os, Item const &m) {
return os << m.value();
};
// Reads from stdin one line at a time
class Reader {
public:
const std::string nextLine() {
std::string line;
std::getline(std::cin, line);
return line;
}
};
// A fake reader that returns a well-known string every time
class FakeReader {
private:
int _count;
public:
const std::string nextLine() {
if (_count++ > 1) {
return "hi";
} else {
return "";
}
}
};
// Evaluator takes two classes as dependencies
// - the instance-dependency "MyReader" is injected as a constructor argument
// - the factory-dependency "MyItem" is injected as a type whose constructor is called at runtime
template<class MyReader, class MyItem>
class Evaluator {
private:
MyReader _reader;
public:
Evaluator(MyReader r): _reader {r} {}
MyItem line() {
// call factory method via constructor
MyItem line {_reader.nextLine()};
return line;
}
};
int main() {
Evaluator<Reader, Item> eval { Reader() };
Evaluator<FakeReader, Item> fake_eval { FakeReader() };
// fake reader runs without input
std::cout << fake_eval.line() << std::endl;
// real reader waits for stdin
std::cout << eval.line() << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment