ヘッダーファイル<any>
で定義されているstd::any
は、ほとんどどんな型の値でも保持できるクラスだ。
#include <any>
int main()
{
std::any a ;
a = 0 ; // int
a = 1.0 ; // double
a = "hello" ; // char const *
std::vector<int> v ;
a = v ; // std::vector<int>
// 保持しているstd::vector<int>のコピー
auto value = std::any_cast< std::vector<int> >( a ) ;
}
any
が保持できない型は、コピー構築できない型だ。
クラスany
はテンプレートではない。そのため宣言は単純だ。
int main()
{
// 値を保持しない
std::any a ;
// int型の値を保持する
std::any b( 0 ) ;
// double型の値を保持する
std::any c( 0.0 ) ;
}
any
が保持する型を事前に指定する必要はない。
クラスany
を破棄すると、そのとき保持していた値が適切に破棄される。
any
のコンストラクターでemplace
をするためにin_place_type
が使える。
struct X
{
X( int, int ) { }
} ;
int main()
{
// 型XをX(1, 2)で構築した結果の値を保持する
std::any a( std::in_place_type<X>, 1, 2 ) ;
}
any
への代入も普通のプログラマーの期待どおりの動きをする。
int main()
{
std::any a ;
std::any b ;
// aはint型の値42を保持する
a = 42 ;
// bはint型の値42を保持する
b = a ;
}
template <class T, class... Args>
decay_t<T>& emplace(Args&&... args);
any
はemplace
メンバー関数をサポートしている。
struct X
{
X( int, int ) { }
} ;
int main()
{
std::any a ;
// 型XをX(1, 2)で構築した結果の値を保持する
a.emplace<X>( 1, 2 ) ;
}
void reset() noexcept ;
any
のreset
メンバー関数は、any
の保持してある値を破棄する。reset
を呼び出した後のany
は値を保持しない。
int main()
{
// aは値を保持しない
std::any a ;
// aはint型の値を保持する
a = 0 ;
// aは値を保持しない
a.reset() ;
}
any
はswap
メンバー関数をサポートしている。
int main()
{
std::any a(0) ;
std::any b(0.0) ;
// aはint型の値を保持
// bはdouble型の値を保持
a.swap(b) ;
// aはdouble型の値を保持
// bはint型の値を保持
}
bool has_value() const noexcept;
any
のhas_value
メンバー関数はany
が値を保持しているかどうかを調べる。値を保持しているならばtrue
を、保持していないならばfalse
を返す。
int main()
{
std::any a ;
// false
bool b1 = a.has_value() ;
a = 0 ;
// true
bool b2 = a.has_value() ;
a.reset() ;
// false
bool b3 = a.has_value() ;
}
const type_info& type() const noexcept;
type
メンバー関数は、保持している型T
のtypeid(T)
を返す。値を保持していない場合、typeid(void)
を返す。
int main()
{
std::any a ;
// typeid(void)
auto & t1 = a.type() ;
a = 0 ;
// typeid(int)
auto & t2 = a.type() ;
a = 0.0 ;
// typeid(double)
auto & t3 = a.type() ;
}
template <class T, class... Args>
any make_any(Args&& ...args);
template <class T, class U, class... Args>
any make_any(initializer_list<U> il, Args&& ...args);
make_any<T>( args... )
はT
型をコンストラクター実引数args...
で構築した値を保持するany
を返す。
struct X
{
X( int, int ) { }
} ;
int main()
{
// int型の値を保持するany
auto a = std::make_any<int>( 0 ) ;
// double型の値を保持するany
auto b = std::make_any<double>( 0.0 ) ;
// X型の値を保持するany
auto c = std::make_any<X>( 1, 2 ) ;
}
template<class T> T any_cast(const any& operand);
template<class T> T any_cast(any& operand);
template<class T> T any_cast(any&& operand);
any_cast<T>(operand)
はoperand
が保持している値を返す。
int main()
{
std::any a(0) ;
int value = std::any_cast<int>(a) ;
}
any_cast<T>
で指定したT
型が、any
が保持している型ではない場合、std::bad_any_cast
がthrow
される。
int main()
{
try {
std::any a ;
std::any_cast<int>(a) ;
} catch( std::bad_any_cast e )
{
// 型を保持していなかった
}
}
template<class T>
const T* any_cast(const any* operand) noexcept;
template<class T>
T* any_cast(any* operand) noexcept;
any_cast<T>
にany
へのポインターを渡すと、T
へのポインター型が返される。any
がT
型を保持している場合はT
型を参照するポインターが返る。保持していない場合は、nullptr
が返る。
int main()
{
std::any a(42) ;
// int型の値を参照するポインター
int * p1 = std::any_cast<int>( &a ) ;
// nullptr
double * p2 = std::any_cast<double>( &a ) ;
}