読者です 読者をやめる 読者になる 読者になる

とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

GCC の std::result_of の挙動があやしい気がする

GCC 4.6.1, 4.7.0 20111001 (experimental) にて。
以下のコードは std::result_of::type でこけます。この挙動って正しいのでしょうか…?

#include<type_traits>

template<class T>
void test()
{}

struct X
{};

int main()
{
 typedef int (X::* const A);
 test<std::result_of<A(X)>::type>();
}

コンパイルエラー:

a.cpp: In function 'int main()':
a.cpp:13:25: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
In file included from a.cpp:1:0:
c:\cygwin\home\risk\misc\gcc4.7\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/c++/4.7.0/type_traits: In instantiation of 'struct std::_Result_of_impl<true, false, int X::* const, X>':
c:\cygwin\home\risk\misc\gcc4.7\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/c++/4.7.0/type_traits:1840:12:   required from 'class std::result_of<int X::* const(X)>'
a.cpp:13:27:   required from here
c:\cygwin\home\risk\misc\gcc4.7\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/c++/4.7.0/type_traits:1821:12: error: invalid use of incomplete type 'struct std::_Result_of_memobj<int X::* const, X>'
c:\cygwin\home\risk\misc\gcc4.7\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/c++/4.7.0/type_traits:1769:12: error: declaration of 'struct std::_Result_of_memobj<int X::* const, X>'
c:\cygwin\home\risk\misc\gcc4.7\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/c++/4.7.0/type_traits:1826:2: error: invalid use of incomplete type 'struct std::_Result_of_memobj<int X::* const, X>'
c:\cygwin\home\risk\misc\gcc4.7\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/c++/4.7.0/type_traits:1769:12: error: declaration of 'struct std::_Result_of_memobj<int X::* const, X>'
a.cpp:13:35: error: no matching function for call to 'test()'
a.cpp:13:35: note: candidate is:
a.cpp:4:6: note: template<class T> void test()
a.cpp:4:6: note:   template argument deduction/substitution failed:
a.cpp:13:35: error: template argument 1 is invalid

どうやら const や volatile で修飾するとダメなようです。以下のコメントアウトしているところすべてでエラーになります。

#include<type_traits>

template<class T>
void test()
{}

struct X
{};

int main()
{
 // cv なければ OK
 {
  typedef int X::* A;
  test<std::result_of<A(X)>::type>();
  typedef int X::*& B;
  test<std::result_of<B(X)>::type>();
  typedef int (X::* C)();
  test<std::result_of<C(X)>::type>();
  typedef int (X::*& D)();
  test<std::result_of<D(X)>::type>();
 }
 // なぜかこける…
 {
  typedef int X::* const A;
  // test<std::result_of<A(X)>::type>();
  typedef int X::* const & B;
  // test<std::result_of<B(X)>::type>();
  typedef int (X::* const C)();
  // test<std::result_of<C(X)>::type>();
  typedef int (X::* const & D)();
  // test<std::result_of<D(X)>::type>();
 }
 {
  typedef int X::* volatile A;
  // test<std::result_of<A(X)>::type>();
  typedef int X::* volatile & B;
  // test<std::result_of<B(X)>::type>();
  typedef int (X::* volatile C)();
  // test<std::result_of<C(X)>::type>();
  typedef int (X::* volatile & D)();
  // test<std::result_of<D(X)>::type>();
 }
 {
  typedef int X::* const volatile A;
  // test<std::result_of<A(X)>::type>();
  typedef int X::* const volatile & B;
  // test<std::result_of<B(X)>::type>();
  typedef int (X::* const volatile C)();
  // test<std::result_of<C(X)>::type>();
  typedef int (X::* const volatile & D)();
  // test<std::result_of<D(X)>::type>();
 }
}

ドラフトの result_of や INVOKE の定義を調べてみましたが,const だとダメという記述は見つけられませんでした。
何がおかしいのだろう…?