Created
December 1, 2017 18:53
-
-
Save BenjaminHolland/c4e209b6b5fc5db925cbd8e79b7d5e7e to your computer and use it in GitHub Desktop.
Strange Overload Resolution Issue.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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