Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save BenjaminHolland/c4e209b6b5fc5db925cbd8e79b7d5e7e to your computer and use it in GitHub Desktop.
Save BenjaminHolland/c4e209b6b5fc5db925cbd8e79b7d5e7e to your computer and use it in GitHub Desktop.
Strange Overload Resolution Issue.
#include <functional>
#include <iostream>
#include <string>
#include <mutex>
#include <thread>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
using namespace std;
//do some aliasing so we can avoid the problem of writing the entire function type every operation.
//This avoids the problem of std::function(lambda...) argument detail erasure.
template <typename T>
using consume = function<void(const T&)>;
template <typename T>
using mutate = function<void(T&)>;
//CRTP for a fairly simple property class.
template <typename T,typename R>
class IFluentProperty {
protected:
//Get a reference to the value.
T& get() {
return static_cast<R*>(this)->get();
}
//get a const reference to the value.
const T& get() const {
return static_cast<R const*>(this)->get();
}
//do some operation that mutates the value;
R& use(mutate<T> manipulator) {
return static_cast<R*>(this)->use(manipulator);
}
//do some operation that uses the value immutably.
R& use(consume<T> manipulator) const {
return static_cast<const R*>(this)->use(manipulator);
}
public:
//make some nice operators for piping.
R& operator>>(mutate<T> manipulator) {
return use(manipulator);
}
//allow this operation to be const, but still return a mutable reference to this property.
//I'm pretty sure this isn't right yet.
R& operator>>(consume<T> manipulator) const {
return use(manipulator);
}
};
template <typename T>
class FluentProperty:public IFluentProperty<T,FluentProperty<T>> {
private:
T _item;
public:
T& get() {
return _item;
}
const T& get() const {
return _item;
}
FluentProperty& use(mutate<T> manipulator) {
//use the manipulator
manipulator(_item);
return *this;
}
FluentProperty& use(consume<T> manipulator) const{
manipulator(_item);
return const_cast<FluentProperty&>(*this);
}
};
int main() {
FluentProperty<int> x;
//check to make sure that the lambda we want to use preseves the constness of it's args. it does.
auto t = consume<int>([](int const& i) {cout << i << "\n"; });
cout << typeid(t).name() << "\n";
//Attempt to pipe the value to the lambda inline. The >> fails overload resolution.
x >> consume<int>([](int const& i) {cout << i << "\n"; });
cout << typeid(t).name();
cin.get();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment