Skip to content

Instantly share code, notes, and snippets.

@XueshiQiao
Last active January 3, 2024 13:26
Show Gist options
  • Save XueshiQiao/1e7a69ac0b2da423b36a4625d354c068 to your computer and use it in GitHub Desktop.
Save XueshiQiao/1e7a69ac0b2da423b36a4625d354c068 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <functional>
using namespace std;
// -std=c++17
template <typename In, typename Out>
class Filter {
public:
using Fn = std::function<Out(In)>;
Filter(Fn fn) : fn_(std::move(fn)) {}
template <typename In_>
Out Process(In_ value) {
static_assert(std::is_same_v<In_, In_>, "type must match");
return fn_(std::forward<In_>(value));
}
private:
Fn fn_;
};
int main(int argc, char *argv[]) {
{
auto filter = Filter<int32_t, std::string>([](int32_t value) -> std::string {
return std::to_string(value);
});
std::cout << "filter: " << filter.Process(100) << std::endl;
}
{
// Bad case 1, auto deduction fail
// // no viable constructor or deduction guide for deduction of template arguments of 'Filter'
// auto filter = Filter([](int32_t value) -> std::string {
// return std::to_string(value);
// });
// std::cout << "filter: " << filter.Process(100) << std::endl;
}
{
std::function<std::string(int32_t)> func = [](int32_t value) {
return std::to_string(value);
};
// auto deduction works, Filter<int32_t, std::string> is not need, Filter is Ok
auto filter = Filter(func);
std::cout << "filter: " << filter.Process(100) << std::endl;
}
{
//Bad case 2, auto deduction fail
// auto func = [](int32_t value) -> std::string{
// return std::to_string(value);
// };
// // no viable constructor or deduction guide for deduction of template arguments of 'Filter'
// auto filter = Filter(func);
// std::cout << "filter: " << filter.Process(100) << std::endl;
}
return 0;
}
@XueshiQiao
Copy link
Author

Solution

#include <iostream>
#include <functional>

using namespace std;

// -std=c++17


template<typename... T>
struct callop_traits;

template<typename L, typename I, typename O>
struct callop_traits<O(L::*)(I) const> {
  using In = I;
  using Out = O;
};

template<typename F>
using get_callop_traits = callop_traits<decltype(&std::remove_reference_t<F>::operator())>;

template<typename F>
using in_t = typename get_callop_traits<F>::In;

template<typename F>
using out_t = typename get_callop_traits<F>::Out;


template <typename In, typename Out> 
class Filter {
public:
  using Fn = std::function<Out(In)>;

  Filter(std::function<Out(In)> fn) : fn_(std::move(fn)) {    
  }

  template <typename In_>
  Out Process(In_ value) {
    static_assert(std::is_same_v<In_, In>, "type must match");
    return fn_(std::forward<In_>(value));
  }

private:
  Fn fn_;
};


// auto deduction guide
template<typename F>
Filter(F&&) -> Filter<in_t<F>, out_t<F>>;


int main(int argc, char *argv[]) {
  
  {
    auto filter = Filter<int32_t, std::string>([](int32_t value) -> std::string {
      return std::to_string(value);
    });
    std::cout << "filter: " << filter.Process(100) << std::endl;
  }
  
  {
    // Bad case 1, auto deduction fail

//  // no viable constructor or deduction guide for deduction of template arguments of 'Filter'
    auto filter = Filter([](int32_t value) -> std::string {
      return std::to_string(value);
    });
    std::cout << "filter: " << filter.Process(100) << std::endl;
  }

  
  {
    std::function<std::string(int32_t)> func = [](int32_t value)  {
      return std::to_string(value);
    };
    
    // auto deduction works, Filter<int32_t, std::string> is not need, Filter is Ok
    auto filter = Filter(func);
    std::cout << "filter: " << filter.Process(100) << std::endl;
  }
  
  
  {
    //Bad case 2, auto deduction fail
    auto func = [](int32_t value) -> std::string{
      return std::to_string(value);
    };
    // no viable constructor or deduction guide for deduction of template arguments of 'Filter'
    auto filter = Filter(func);
    std::cout << "filter: " << filter.Process(100) << std::endl;
  }
  return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment