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

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

const が消える件…

[追記]解決しました。初めのコード(↓)自体に問題があるので,余計ややこしくなってました。
これは知らなかった…。g の挙動にビビる…。なぜ const が消えるんだ…。

#include<iostream>
#include<type_traits>

template<class T>
void f(T&)
{
 std::cout << std::boolalpha << std::is_const<T>::value << std::endl;
}

template<class T>
void g(T&&)
{
 std::cout << std::boolalpha << std::is_const<T>::value << std::endl;
}

int main()
{
 {
  int i = 0;
  f(i);
  int const ic = 0;
  f(ic);
  int& ilr = i;
  f(ilr);
  int const & iclr = ic;
  f(iclr);
  int&& irr = 0;
  f(irr);
  int const && icrr = 0;
  f(icrr);
  std::cout << "**********" << std::endl;
 }
 {
  int i = 0;
  g(i);
  int const ic = 0;
  g(ic);
  int& ilr = i;
  g(ilr);
  int const & iclr = ic;
  g(iclr);
  int&& irr = 0;
  g(irr);
  int const && icrr = 0;
  g(icrr);
  std::cout << "**********" << std::endl;
 }
}

実行結果:

false
true
false
true
false
true
**********
false
false
false
false
false
false
**********

const を保存(?)するにはどうしたらいいんだろう?

template<class T>
void g(T const &);

こういうオーバーロードを用意して,add_const::type するのが正しいのかな?
ほんとわけわからん。

追記

コメントおよびトラックバックで解決。ありがとうございました。
const は残っていました。ただ参照(&)が残っているので,remove_reference してからでないと,is_const で正しく判断できないようです。
また,テストコードの以下の部分が間違っていました。

  int&& irr = 0;
  g(irr);
  int const && icrr = 0;
  g(icrr);

こっちが正しい。

  int&& irr = 0;
  g(std::move(irr));  // あるいは g(0)
  int const && icrr = 0;
  g(std::move(icrr)); // あるいは g(0)

rvalue reference 自体は lvalue なので,rvalue を渡すには move するか,値をそのまま渡すのが正しい。