fork download
  1. #include <functional>
  2. #include <iostream>
  3. #include <type_traits>
  4.  
  5. template<typename T>
  6. struct Provider final {
  7. Provider() = delete;
  8. Provider(const Provider& other) : _callback{ other._callback } {}
  9. Provider(Provider&& other) : _callback{ std::move(other._callback) } {}
  10.  
  11. Provider& operator=(Provider&& other) {
  12. std::swap(other._callback, _callback);
  13. return *this;
  14. }
  15.  
  16. Provider& operator=(const Provider& other) {
  17. _callback = other._callback;
  18. return *this;
  19. }
  20.  
  21. template<typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type, typename = typename std::enable_if<!std::is_same<U, T>::value>::type>
  22. Provider<T>& operator=(Provider<U>&& other) {
  23. std::swap(other._callback, _callback);
  24. return *this;
  25. }
  26.  
  27. template<typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type, typename = typename std::enable_if<!std::is_same<U, T>::value>::type>
  28. Provider<T>& operator=(const Provider<U>& other) {
  29. _callback = other._callback;
  30. return *this;
  31. }
  32.  
  33. template<typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type, typename = typename std::enable_if<!std::is_same<U, T>::value>::type>
  34. Provider(const Provider<U>& other) : _callback{ other._callback } {}
  35.  
  36. template<typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type, typename = typename std::enable_if<!std::is_same<U, T>::value>::type>
  37. Provider(Provider<U>&& other) : _callback{ std::move(other._callback) } {}
  38.  
  39. template<typename U, typename = typename std::enable_if<std::is_constructible<std::function<T()>, U>::value>::type>
  40. Provider(U callback) : _callback{ callback } {}
  41.  
  42. template<typename = typename std::enable_if<!std::is_constructible<std::function<T()>, T>::value, T>::type>
  43. Provider(T value) : _callback{[=] { return value; }} {}
  44.  
  45. template<typename U>
  46. friend struct Provider;
  47.  
  48. T operator()() const {
  49. return _callback();
  50. }
  51.  
  52. private:
  53. std::function<T()> _callback;
  54. };
  55.  
  56. template<typename T>
  57. void doSomething(Provider<T> p) {
  58. std::cout << "My value is:" << p() << std::endl;
  59. }
  60.  
  61. int main()
  62. {
  63. Provider<int> p1 = 9;
  64. Provider<double> p2 = [] { return 9.4; };
  65. Provider<unsigned int> p3{9};
  66. Provider<float> p4{[]{ return 9.4f; }};
  67.  
  68. doSomething<unsigned int>(5);
  69. doSomething<float>([] { return 9.5f; });
  70. doSomething<int>(p1);
  71. doSomething<double>(p2);
  72.  
  73. return 0;
  74. }
  75.  
  76.  
Success #stdin #stdout 0s 3416KB
stdin
Standard input is empty
stdout
My value is:5
My value is:9.5
My value is:9
My value is:9.4