How to make negate_unary work with any type?

Following this question: How to cancel a predicate function using an operator! in c ++?
I want to create an operator! can work with any functor inherited from unary_function. I tried:

template<typename T>
inline std::unary_negate<T> operator !( const T& pred ) {
 return std::not1( pred );
}

The compiler complained:

Error 5 error C2955: 'std::unary_function' : use of class template requires template argument list c:\program files\microsoft visual studio 10.0\vc\include\xfunctional 223 1 Graphic
Error 7 error C2451: conditional expression of type 'std::unary_negate<_Fn1>' is illegal c:\program files\microsoft visual studio 10.0\vc\include\ostream 529 1 Graphic
Error 3 error C2146: syntax error : missing ',' before identifier 'argument_type' c:\program files\microsoft visual studio 10.0\vc\include\xfunctional 222 1 Graphic
Error 4 error C2065: 'argument_type' : undeclared identifier c:\program files\microsoft visual studio 10.0\vc\include\xfunctional 222 1 Graphic
Error 2 error C2039: 'argument_type' : is not a member of 'std::basic_ostream<_Elem,_Traits>::sentry' c:\program files\microsoft visual studio 10.0\vc\include\xfunctional 222 1 Graphic
Error 6 error C2039: 'argument_type' : is not a member of 'std::basic_ostream<_Elem,_Traits>::sentry' c:\program files\microsoft visual studio 10.0\vc\include\xfunctional 230 1 Graphic

Any idea?

Update
Follow the solution "templatetypedef", I received a new error:

Error 3 error C2831: 'operator !' cannot have default parameters c:\visual studio 2010 projects\graphic\graphic\main.cpp 39 1 Graphic
Error 2 error C2808: unary 'operator !' has too many formal parameters c:\visual studio 2010 projects\graphic\graphic\main.cpp 39 1 Graphic
Error 4 error C2675: unary '!' : 'is_prime' does not define this operator or a conversion to a type acceptable to the predefined operator c:\visual studio 2010 projects\graphic\graphic\main.cpp 52 1 Graphic

Update 1
Full Code:

#include <iostream>
#include <functional>
#include <utility>
#include <cmath>
#include <algorithm>
#include <iterator>
#include <string>

#include <boost/assign.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/std/map.hpp>
#include <boost/assign/std/set.hpp>
#include <boost/assign/std/list.hpp>
#include <boost/assign/std/stack.hpp>
#include <boost/assign/std/deque.hpp>

struct is_prime : std::unary_function<int, bool> {
 bool operator()( int n ) const {
  if( n < 2 )
   return 0;
  if( n == 2 || n == 3 )
   return 1;
  if( n % 2 == 0 || n % 3 == 0 )
   return 0;
  int upper_bound = std::sqrt( static_cast<double>( n ) );
  for( int pf = 5, step = 2; pf <= upper_bound; ) {
   if( n % pf == 0 )
    return 0;
   pf  += step;
   step = 6 - step;
  }
  return 1;
 }
};

/*
template<typename T>
inline std::unary_negate<T> operator !( const T& pred, typename T::argument_type* dummy = 0 ) {
 return std::not1<T>( pred );
}
*/

inline std::unary_negate<is_prime> operator !( const is_prime& pred ) {
 return std::not1( pred );
}

template<typename T>
inline void print_con( const T& con, const std::string& ms = "", const std::string& sep = ", " ) {
 std::cout << ms << '\n';
 std::copy( con.begin(), con.end(), std::ostream_iterator<typename T::value_type>( std::cout, sep.c_str() ) );
 std::cout << "\n\n";
}

int main() {
 using namespace boost::assign;
 std::vector<int> nums;
 nums += 1, 3, 5, 7, 9;
 nums.erase( remove_if( nums.begin(), nums.end(), !is_prime() ), nums.end() );
 print_con( nums, "After remove all primes" ); 
}

Thanks,
Chan Nguyen

+3
source share
3 answers

" - " (SFINAE). , , ++ , . . , (.. , ), , , , - .

. -, , "IsAdaptable", , . , operator ! , ? , SFINAE, - , . , "enable if". enable-if:

template <bool Condition, typename T> struct EnableIf {
     typedef T type;
};
template <typename T> struct EnableIf<false, T> {
     // Empty
};

. - - , , EnableIf type, , .

enable if , , , . , , ​​, :

template <typename T>
ReturnType MyFunction(/* ... arguments ... */) {
    /* ... body ... */
}

, , T "Predicate". :

template <typename T>
typename EnableIf<Predicate<T>::value, ActualReturnType>::type MyFunction(/* ... arguments ... */) {
    /* ... body here ... */
}

, MyFunction T, . -, Predicate<T>::value , EnableIf type, ActualReturnType, . , Predicate<T>::value , EnableIf type, . , " ", . , , . , , MyFunction .

, operator ! :

template <typename Pred>
typename EnableIf<IsAdaptable<Pred>::value, std::unary_negate<Pred> >::type
operator! (const Pred& p) {
     return std::not1(p);
}

, : " operator ! , ". - IsAdaptable, .

, IsAdaptable . , , . ! , .

, IsAdaptable, - SFINAE . . , , , , "" , "", , "" "", "" , - . :

  • , , . , "" "" "" .
  • , , . , , "", , .

? , , :

template <typename T> Yes TestFunction(typename T::argument_type* argument);
template <typename T> No  TestFunction(...);

TestFunction. T a T::argument_type*. varargs. , T :

TestFunction<T>(NULL);

, T , argument_type, . . - , ++, varargs (, ...) - , . , Yes, T argument_type, , No . - - , , , , T !

, , . , Yes No, :

typedef char Yes;
struct No {
    char dummy[32];
};

, sizeof(Yes) == 1 sizeof(No) > 1. IsAdaptable:

template <typename T> struct IsAdaptable {
private:
    typedef char Yes;
    struct No {
         char dummy[32];
    };

    template <typename U> static Yes test(typename U::argument_type*);
    template <typename U> static No  test(...);

public:
    static const bool value = (sizeof(test<T>(0)) == sizeof(Yes));
};

, true, test<T>(0) Yes false . , sizeof ( , ), .

:

template <bool cond, typename T> struct EnableIf {
  typedef T type;
};
template <typename T> struct EnableIf<false, T> {

};

template <typename T> struct IsAdaptable {
private:
  typedef char Yes;
  struct No {
    char buffer[32];
  };

  template <typename U> static Yes test(typename U::argument_type*);
  template <typename U> static No  test(...);

public:
  static const bool result = (sizeof(test<T>(0)) == sizeof(Yes));
};

template<typename T>                                                                                                                                           
inline typename EnableIf<IsAdaptable<T>::result, std::unary_negate<T> >::type operator !(const T& pred) {                                                      
  return std::not1( pred );                                                                                                                                    
}  

, !

+3

, , ++. , operator !() . std::unary_negate<> , argument_type typedef, , , typedef.

, , . , : std::not1(). ? , std::not1(f), !f , .

+2

, , , std:: unary_function , ?

?

0

Source: https://habr.com/ru/post/1783491/


All Articles