samedi 16 novembre 2019

how to define a class memeber function with c++::enable_if outside of a class declaration

I am using gcc 4.8.4 with -std=c++11

Originally I have this simplified minimum code below ( since the definition of function is quite complex, I implemented template class definition outside of class declaration ).

#include <type_traits>
#include <iostream>


template< class A, class B >
class HAHA
{
  public :

    HAHA( void );
    ~HAHA( void );
    HAHA( const HAHA & o );

    void set_value( int i ) { _inner_value = i;    }
    int  value    ( void  ) { return _inner_value; }

    HAHA & operator= ( const HAHA & o );
    HAHA   operator+ ( const A    & o );
    HAHA   operator+ ( const B    & o );

  private :
    int _inner_value;
};

template< class A, class B >
HAHA< A, B >::HAHA( void )
  : _inner_value( 0 )
{
}


template< class A, class B >
HAHA< A, B >::~HAHA( void )
{
}


template< class A, class B >
HAHA< A, B >::HAHA( const HAHA & o )
  : _inner_value( o._inner_value )
{
}


template< class A, class B >
HAHA< A, B > &
HAHA< A, B >::operator= ( const HAHA & o )
{
  _inner_value = o._inner_value;
  return *this;
}


template< class A, class B >
HAHA< A, B >
HAHA< A, B >::operator+( const A & o )
{
  HAHA res;
  res._inner_value = _inner_value + o;
  return res;
}


template< class A, class B >
HAHA< A, B >
HAHA< A, B >::operator+( const B & o )
{
  HAHA res;
  res._inner_value = _inner_value + o;
  return res;
}



int test1( )
{
  HAHA< int, long > hehe;
  hehe.set_value( 3 );

  HAHA< int, long > hi;

  hi = hehe + int(4);

  std::cout << hi.value( ) << std::endl;
  return 0;
}


int test2( )
{
  HAHA< int, int > hehe;
  hehe.set_value( 3 );

  HAHA< int, int > hi;

  hi = hehe + 4;

  std::cout << hi.value( ) << std::endl;
  return 0;
}


int main( )
{
  return test2( );
}

The code above can run test1, but in test2, there is an ambiguous in instantiating. However, I need both oprator+ functions to work in other tests. So I cannot just remove one operator+ function. After some learning, I was told that I should use std::enable_if together with std::is_name. So I changed my code like :

template< class A, class B >
class HAHA
{
  public :

    ...
    HAHA operator+ ( const A & o );
    typename std::enable_if< !std::is_same< A, B >::value, HAHA >::type
    operator+ ( const B & o );
    ...
};
...
template< class A, class B >
typename std::enable_if< !std::is_same< A, B >::value, HAHA<A,B> >::type   <-- error reported that this line is not right
HAHA< A, B >::operator+( const B & o )
{
  HAHA res;
  res._inner_value = _inner_value + o;
  return res;
}

And then I got this error :

test_meta.cpp: In instantiation of ‘class HAHA<int, int>’:
test_meta.cpp:82:20:   required from here
test_meta.cpp:57:1: error: no type named ‘type’ in ‘struct std::enable_if<false, HAHA<int, int> >’
 HAHA< A, B >::operator+( const B & o )
 ^

How should I change my code ? many thanks!!!!

Aucun commentaire:

Enregistrer un commentaire