associated typeは実に不思議だ。大抵は関数の戻り値の型を表すのに使われる。(14.9.1.2.2)。どうも、ネストされた型として使えるようだ。
auto concept Foo < typename T >
{
requires std::CopyConstructible< T > ;
typename type ;
type T::func() ;
}
template < typename T > requires Foo< T >
void f( T x )
{
x.func() ;
// T::typeが使える。
std::cout << typeid(typename T::type).name() << std::endl ;
}
struct Bar
{
Bar func(){ return Bar() ; }
} ;
int main()
{
f(Bar()) ;
}
しかし、以下のコードはコンパイルできない。
auto concept Foo < typename T >
{
requires std::CopyConstructible< T > ;
typename type ;
}
template < typename T > requires Foo< T >
void f( T x )
{
std::cout << typeid(typename T::type).name() << std::endl ;
}
struct Bar
{
typedef Bar type ;
} ;
int main()
{
f(Bar()) ;
}
もし、associated typeで、テンプレートパラメーターのネストされた同名の型を使いたい場合は、default valueを使うことで実現できる。
auto concept Foo < typename T >
{
requires std::CopyConstructible< T > ;
typename type = T::type ;
}
なお、concept_mapで別名を割り当てることも可能だ。例えば、Bar::typeではなく、Bar::typoだったとしても、concept_mapを使えば、ご覧の通り。
struct Bar
{
typedef Bar typo ;// おおっと!
} ;
concept_map Foo< Bar >
{
typedef Bar::typo type ;// おkおk
}
そういえば、今までクラス内部でネストされたtypedefをなんと言うのか分からず、いろんな表現を使っていたが、規格用語としては、Nested type names(9.9)というらしい。そのまんまだ。
No comments:
Post a Comment