関数テンプレートにおける右辺値識別

完全に個人的なメモなので気にしないよ〜に.

#include <iostream>

#include <boost/mpl/identity.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_volatile.hpp>
#include <boost/static_assert.hpp>

struct volatile_refused;

template< class T, class R = void >
struct refuse_volatile
  : public boost::mpl::if_<
        boost::is_volatile< T >
      , volatile_refused
      , boost::mpl::identity< R >
      >::type
{};

template< class T >
typename refuse_volatile< T, void >::type
discriminate( T & )
{
  std::cout << "L" << std::endl;
}

template< class T >
void discriminate( T const volatile & )
{
  // If you want to get nonvolatile `T', use `const_cast< T const & >' here.
  // Such `const_cast' is completely legal.
  std::cout << "R" << std::endl;
}



int return_rvalue()
{
  return 0;
}

int const return_const_rvalue()
{
  return 0;
}

int main()
{
  int i = 0;
  discriminate( i );                     // -> "L".
  int const ci = 0;
  discriminate( ci );                    // -> "L".
  discriminate( 0 );                     // -> "R".
  discriminate( return_rvalue() );       // -> "R".
  discriminate( return_const_rvalue() ); // -> False "L".
                                         // This is the only remaining
                                         // problem. In the current standard,
                                         // this may be unsolvable (If it
                                         // were resolved, it would be an
                                         // rvalue reference emulation).
  int volatile vi = 0;
  //discriminate( vi );       // Triggers an expected compile error.
  int const volatile cvi = 0;
  //discriminate( cvi );      // Triggers an expceted compile error.
}

#あ,違うわ.右辺値識別は(ほぼ)解けているけれど the Perfect Forwarding にはなってないや.