@ -23,6 +23,8 @@
# include "gmock/gmock.h"
# include "gtest/gtest.h"
# include "absl/base/attributes.h"
# include "absl/memory/memory.h"
# include "absl/strings/str_cat.h"
namespace {
@ -38,8 +40,9 @@ namespace {
# pragma warning( disable : 4101 ) // unreferenced local variable
# endif // _MSC_VER
using testing : : StaticAssertTypeEq ;
using testing : : ElementsAre ;
using : : testing : : ElementsAre ;
using : : testing : : Pointee ;
using : : testing : : StaticAssertTypeEq ;
TEST ( IntegerSequenceTest , ValueType ) {
StaticAssertTypeEq < int , absl : : integer_sequence < int > : : value_type > ( ) ;
@ -159,5 +162,176 @@ TEST(IndexSequenceForTest, Example) {
ElementsAre ( " 12 " , " abc " , " 3.14 " ) ) ;
}
int Function ( int a , int b ) { return a - b ; }
int Sink ( std : : unique_ptr < int > p ) { return * p ; }
std : : unique_ptr < int > Factory ( int n ) { return absl : : make_unique < int > ( n ) ; }
void NoOp ( ) { }
struct ConstFunctor {
int operator ( ) ( int a , int b ) const { return a - b ; }
} ;
struct MutableFunctor {
int operator ( ) ( int a , int b ) { return a - b ; }
} ;
struct EphemeralFunctor {
EphemeralFunctor ( ) { }
EphemeralFunctor ( const EphemeralFunctor & ) { }
EphemeralFunctor ( EphemeralFunctor & & ) { }
int operator ( ) ( int a , int b ) & & { return a - b ; }
} ;
struct OverloadedFunctor {
OverloadedFunctor ( ) { }
OverloadedFunctor ( const OverloadedFunctor & ) { }
OverloadedFunctor ( OverloadedFunctor & & ) { }
template < typename . . . Args >
std : : string operator ( ) ( const Args & . . . args ) & {
return absl : : StrCat ( " & " , args . . . ) ;
}
template < typename . . . Args >
std : : string operator ( ) ( const Args & . . . args ) const & {
return absl : : StrCat ( " const& " , args . . . ) ;
}
template < typename . . . Args >
std : : string operator ( ) ( const Args & . . . args ) & & {
return absl : : StrCat ( " && " , args . . . ) ;
}
} ;
struct Class {
int Method ( int a , int b ) { return a - b ; }
int ConstMethod ( int a , int b ) const { return a - b ; }
int member ;
} ;
struct FlipFlop {
int ConstMethod ( ) const { return member ; }
FlipFlop operator * ( ) const { return { - member } ; }
int member ;
} ;
TEST ( ApplyTest , Function ) {
EXPECT_EQ ( 1 , absl : : apply ( Function , std : : make_tuple ( 3 , 2 ) ) ) ;
EXPECT_EQ ( 1 , absl : : apply ( & Function , std : : make_tuple ( 3 , 2 ) ) ) ;
}
TEST ( ApplyTest , NonCopyableArgument ) {
EXPECT_EQ ( 42 , absl : : apply ( Sink , std : : make_tuple ( absl : : make_unique < int > ( 42 ) ) ) ) ;
}
TEST ( ApplyTest , NonCopyableResult ) {
EXPECT_THAT ( absl : : apply ( Factory , std : : make_tuple ( 42 ) ) ,
: : testing : : Pointee ( 42 ) ) ;
}
TEST ( ApplyTest , VoidResult ) { absl : : apply ( NoOp , std : : tuple < > ( ) ) ; }
TEST ( ApplyTest , ConstFunctor ) {
EXPECT_EQ ( 1 , absl : : apply ( ConstFunctor ( ) , std : : make_tuple ( 3 , 2 ) ) ) ;
}
TEST ( ApplyTest , MutableFunctor ) {
MutableFunctor f ;
EXPECT_EQ ( 1 , absl : : apply ( f , std : : make_tuple ( 3 , 2 ) ) ) ;
EXPECT_EQ ( 1 , absl : : apply ( MutableFunctor ( ) , std : : make_tuple ( 3 , 2 ) ) ) ;
}
TEST ( ApplyTest , EphemeralFunctor ) {
EphemeralFunctor f ;
EXPECT_EQ ( 1 , absl : : apply ( std : : move ( f ) , std : : make_tuple ( 3 , 2 ) ) ) ;
EXPECT_EQ ( 1 , absl : : apply ( EphemeralFunctor ( ) , std : : make_tuple ( 3 , 2 ) ) ) ;
}
TEST ( ApplyTest , OverloadedFunctor ) {
OverloadedFunctor f ;
const OverloadedFunctor & cf = f ;
EXPECT_EQ ( " & " , absl : : apply ( f , std : : tuple < > { } ) ) ;
EXPECT_EQ ( " & 42 " , absl : : apply ( f , std : : make_tuple ( " 42 " ) ) ) ;
EXPECT_EQ ( " const& " , absl : : apply ( cf , std : : tuple < > { } ) ) ;
EXPECT_EQ ( " const& 42 " , absl : : apply ( cf , std : : make_tuple ( " 42 " ) ) ) ;
EXPECT_EQ ( " && " , absl : : apply ( std : : move ( f ) , std : : tuple < > { } ) ) ;
OverloadedFunctor f2 ;
EXPECT_EQ ( " && 42 " , absl : : apply ( std : : move ( f2 ) , std : : make_tuple ( " 42 " ) ) ) ;
}
TEST ( ApplyTest , ReferenceWrapper ) {
ConstFunctor cf ;
MutableFunctor mf ;
EXPECT_EQ ( 1 , absl : : apply ( std : : cref ( cf ) , std : : make_tuple ( 3 , 2 ) ) ) ;
EXPECT_EQ ( 1 , absl : : apply ( std : : ref ( cf ) , std : : make_tuple ( 3 , 2 ) ) ) ;
EXPECT_EQ ( 1 , absl : : apply ( std : : ref ( mf ) , std : : make_tuple ( 3 , 2 ) ) ) ;
}
TEST ( ApplyTest , MemberFunction ) {
std : : unique_ptr < Class > p ( new Class ) ;
std : : unique_ptr < const Class > cp ( new Class ) ;
EXPECT_EQ (
1 , absl : : apply ( & Class : : Method ,
std : : tuple < std : : unique_ptr < Class > & , int , int > ( p , 3 , 2 ) ) ) ;
EXPECT_EQ ( 1 , absl : : apply ( & Class : : Method ,
std : : tuple < Class * , int , int > ( p . get ( ) , 3 , 2 ) ) ) ;
EXPECT_EQ (
1 , absl : : apply ( & Class : : Method , std : : tuple < Class & , int , int > ( * p , 3 , 2 ) ) ) ;
EXPECT_EQ (
1 , absl : : apply ( & Class : : ConstMethod ,
std : : tuple < std : : unique_ptr < Class > & , int , int > ( p , 3 , 2 ) ) ) ;
EXPECT_EQ ( 1 , absl : : apply ( & Class : : ConstMethod ,
std : : tuple < Class * , int , int > ( p . get ( ) , 3 , 2 ) ) ) ;
EXPECT_EQ ( 1 , absl : : apply ( & Class : : ConstMethod ,
std : : tuple < Class & , int , int > ( * p , 3 , 2 ) ) ) ;
EXPECT_EQ ( 1 , absl : : apply ( & Class : : ConstMethod ,
std : : tuple < std : : unique_ptr < const Class > & , int , int > (
cp , 3 , 2 ) ) ) ;
EXPECT_EQ ( 1 , absl : : apply ( & Class : : ConstMethod ,
std : : tuple < const Class * , int , int > ( cp . get ( ) , 3 , 2 ) ) ) ;
EXPECT_EQ ( 1 , absl : : apply ( & Class : : ConstMethod ,
std : : tuple < const Class & , int , int > ( * cp , 3 , 2 ) ) ) ;
EXPECT_EQ ( 1 , absl : : apply ( & Class : : Method ,
std : : make_tuple ( absl : : make_unique < Class > ( ) , 3 , 2 ) ) ) ;
EXPECT_EQ ( 1 , absl : : apply ( & Class : : ConstMethod ,
std : : make_tuple ( absl : : make_unique < Class > ( ) , 3 , 2 ) ) ) ;
EXPECT_EQ (
1 , absl : : apply ( & Class : : ConstMethod ,
std : : make_tuple ( absl : : make_unique < const Class > ( ) , 3 , 2 ) ) ) ;
}
TEST ( ApplyTest , DataMember ) {
std : : unique_ptr < Class > p ( new Class { 42 } ) ;
std : : unique_ptr < const Class > cp ( new Class { 42 } ) ;
EXPECT_EQ (
42 , absl : : apply ( & Class : : member , std : : tuple < std : : unique_ptr < Class > & > ( p ) ) ) ;
EXPECT_EQ ( 42 , absl : : apply ( & Class : : member , std : : tuple < Class & > ( * p ) ) ) ;
EXPECT_EQ ( 42 , absl : : apply ( & Class : : member , std : : tuple < Class * > ( p . get ( ) ) ) ) ;
absl : : apply ( & Class : : member , std : : tuple < std : : unique_ptr < Class > & > ( p ) ) = 42 ;
absl : : apply ( & Class : : member , std : : tuple < Class * > ( p . get ( ) ) ) = 42 ;
absl : : apply ( & Class : : member , std : : tuple < Class & > ( * p ) ) = 42 ;
EXPECT_EQ ( 42 , absl : : apply ( & Class : : member ,
std : : tuple < std : : unique_ptr < const Class > & > ( cp ) ) ) ;
EXPECT_EQ ( 42 , absl : : apply ( & Class : : member , std : : tuple < const Class & > ( * cp ) ) ) ;
EXPECT_EQ ( 42 ,
absl : : apply ( & Class : : member , std : : tuple < const Class * > ( cp . get ( ) ) ) ) ;
}
TEST ( ApplyTest , FlipFlop ) {
FlipFlop obj = { 42 } ;
// This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
// ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
EXPECT_EQ ( 42 , absl : : apply ( & FlipFlop : : ConstMethod , std : : make_tuple ( obj ) ) ) ;
EXPECT_EQ ( 42 , absl : : apply ( & FlipFlop : : member , std : : make_tuple ( obj ) ) ) ;
}
} // namespace