Search code examples
c++c++11boostenable-if

how to I use SFINAE for function objects with different operator() methods


I wanted to use SFINAE to function objects. For example:

struct functor_1_tag{  };
struct functor_2_tag{  };
struct functor_3_tag{  };

template<typename Graph_t>
struct functor { 
  functor() {  };
  functor(Graph_t& G) : m_G(G) {  } 

  template<typename vertex_t>
  void operator(vertex_t  vertex) { 
    /// do stuff with vertex
  } 
private: 
  Graph_t& m_G;
};

// Similary another 2 functors that have operator()  doing different tasks. 

//Usecase:
// just for 2 functors here 
typedef std::conditional <true, functor_1_tag, functor_2_tag>::type  funct_type;

/// functor --> shud be selected based upon conditional above.?? 
auto func = std::bind(functor<graph>, G, std::placeholders::_1);

// use in algorithm for vertices
std::for_each(vertexset.begin(), vertexset.end(), func );

The do stuff with vertex ( essentially the operator()) is different based upon the functor tags and I want to overload these three functors based upon tags or any other methods such as std::conditional, or std::enable_if or any nested condition checker.

I was able to achieve the same thing for my standard functions. but I am not sure how to do it for functors. The thing is that functors differ only in their operator() implementation and I dont want to overload the operator() methods.

Tag dispatch for functions:

 struct func1_tag{ };
 struct func2_tag{ };

 void do_this(int x) 
 {
    do_this_actually( int x, dispatch() );
 }

 do_this_actually(int x, func1_tag) {  //do stuff  }
 do_this_actually(int x, func2_tag) { // ... } 

 typedef   std::conditional<true, func1_tag, func2_tag>::type  dispatch;

this is for functions. but I am not sure how to use it for function objects. i tried binding the tags to 2nd arguments of the functor. no luck!


Solution

  • I am not sure to understand the complexity of your problem, so either I missed the point or you are overcomplicating your case… Why not create different functors and just select which one to use with the conditional?

    struct functor1 { … };
    struct functor2 { … };
    
    using functor = std::conditional<condition, functor1, functor2>::type;
    
    std::for_each(v.begin(), v.end(), functor());