実は、このコードはコンパイルが通る。規格には特別なルールがあり、テンプレート引数を、rvalue referenceとして関数の引数に使った場合のargument deductionで、lvalueを渡すと、lvalue referenceとなるのである。

#include <iostream>
#include <type_traits>
#include <utility>
#include <boost/current_function.hpp>

template <typename T>
struct f {
  void operator()(T&& x) {
    std::cout << BOOST_CURRENT_FUNCTION << "\n";
  }

  void operator()(T& x) {
    std::cout << BOOST_CURRENT_FUNCTION << "\n";
  }
};

template <typename T>
inline void g(T&& x) {
  std::cout << BOOST_CURRENT_FUNCTION << "\n";
  f<typename std::remove_reference<T>::type>()(std::forward<T>(x));
}

// 特別なルール!
// template <typename T>
// inline void g(T& x) {
//   std::cout << BOOST_CURRENT_FUNCTION << "\n";
// }

int main(int argc, char* argv[]) {
  int x = 42;
  int const y = 42;
  g(42);
  g(x);
  g(y);
  return 0;
}

実行結果


void g(T&&) [with T = int]
void f<T>::operator()(T&&) [with T = int]
void g(T&&) [with T = int&]
void f<T>::operator()(T&) [with T = int]
void g(T&&) [with T = const int&]
void f<T>::operator()(T&) [with T = const int]

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

メンバーのみ編集できます