Wikipedia の decltype についての記事を見るのがいいよ!
- 型
T
へのポインタT* p
が指す先をdecltype(*p)
と書くとT&
となる - 型
T
へのconst
ポインタconst T* p
が指す先をdecltype(*p)
と書くとconst T&
となる - 型
T&
から参照を外すにはstd::remove_reference<>
を使う - 型
const T
からconst
を外すにはstd::remove_const<>
を使う - 型
T*
ポインタを外すにはstd::remove_pointer<>
を使う
のだと思う。たぶん。
以下のようなコードがあるとき
#include <stdio.h>
#include <string.h>
int main() {
const char* p = "TEST";
char b[256];
return puts(strcpy(b, p));
}
// TEST
「p
が指す型に合わせて b
の型も変わって欲しい、でもテンプレート関数は嫌」
という場合に decltype
を使って
// ERROR
#include <stdio.h>
#include <string.h>
int main() {
const char* p = "TEST";
decltype(*p) b[256];
return puts(strcpy(b, p));
}
// ERROR
などと書きたいが、これはエラーになる。
エラーでは参照が云々とか言われるがよく分からないので、
以下のコードで decltype(*p)
の型が何なのかを見てみると
#include <type_traits>
#include <stdio.h>
int main() {
const char* p = "TEST";
printf("%d, %d, %d, %d\n"
, std::is_same<const char&, decltype(*p)>::value
, std::is_same<const char , decltype(*p)>::value
, std::is_same< char&, decltype(*p)>::value
, std::is_same< char , decltype(*p)>::value
);
return 0;
}
// 1, 0, 0, 0
となるので、decltype(*p)
は const char&
だということが分かった。
そこで &
と const
をはずすことを目標にする。
まず、&
をはずすには std::remove_reference<>
を使う
#include <type_traits>
#include <stdio.h>
int main() {
const char* p = "TEST";
printf("%d, %d, %d, %d\n"
, std::is_same<const char&, std::remove_reference<decltype(*p)>::type>::value
, std::is_same<const char , std::remove_reference<decltype(*p)>::type>::value
, std::is_same< char&, std::remove_reference<decltype(*p)>::type>::value
, std::is_same< char , std::remove_reference<decltype(*p)>::type>::value
);
return 0;
}
// 0, 1, 0, 0
次に、const
をはずすには std::remove_const<>
を使う
#include <type_traits>
#include <stdio.h>
int main() {
const char* p = "TEST";
printf("%d, %d, %d, %d\n"
, std::is_same<const char&, std::remove_const<std::remove_reference<decltype(*p)>::type>::type>::value
, std::is_same<const char , std::remove_const<std::remove_reference<decltype(*p)>::type>::type>::value
, std::is_same< char&, std::remove_const<std::remove_reference<decltype(*p)>::type>::type>::value
, std::is_same< char , std::remove_const<std::remove_reference<decltype(*p)>::type>::type>::value
);
return 0;
}
// 0, 0, 0, 1
この結果をもとにして、以下のように書くことで目的は果たせた
#include <type_traits>
#include <stdio.h>
#include <string.h>
int main() {
const char* p = "TEST";
std::remove_const<std::remove_reference<decltype(*p)>::type>::type b[256];
return puts(strcpy(b, p));
}
// TEST
不細工だなー
p
に対して直接 std::remove_pointer<>
使うのではなく、
decltype
を付けてから使う
#include <type_traits>
#include <stdio.h>
int main() {
const char* p = "TEST";
printf("%d, %d, %d, %d\n"
, std::is_same<const char&, std::remove_pointer<decltype(p)>::type>::value
, std::is_same<const char , std::remove_pointer<decltype(p)>::type>::value
, std::is_same< char&, std::remove_pointer<decltype(p)>::type>::value
, std::is_same< char , std::remove_pointer<decltype(p)>::type>::value
);
return 0;
}
// 0, 1, 0, 0
あとは std::remove_const<>
を使って const
を外す
#include <type_traits>
#include <stdio.h>
int main() {
const char* p = "TEST";
printf("%d, %d, %d, %d\n"
, std::is_same<const char&, std::remove_const<std::remove_pointer<decltype(p)>::type>::type>::value
, std::is_same<const char , std::remove_const<std::remove_pointer<decltype(p)>::type>::type>::value
, std::is_same< char&, std::remove_const<std::remove_pointer<decltype(p)>::type>::type>::value
, std::is_same< char , std::remove_const<std::remove_pointer<decltype(p)>::type>::type>::value
);
return 0;
}
// 0, 0, 0, 1
最終的には以下のようになった
#include <type_traits>
#include <stdio.h>
#include <string.h>
int main() {
const char* p = "TEST";
std::remove_const<std::remove_pointer<decltype(p)>::type>::type b[256];
return puts(strcpy(b, p));
}
// TEST
あんまり変わらなかった。残念
auto
のルールから、ポインタの指す先を auto
で受け取ると、そのまま値となる
#include <type_traits>
#include <stdio.h>
int main() {
const char* p = "TEST";
auto c = *p;
printf("%d, %d, %d, %d\n"
, std::is_same<const char&, decltype(c)>::value
, std::is_same<const char , decltype(c)>::value
, std::is_same< char&, decltype(c)>::value
, std::is_same< char , decltype(c)>::value
);
return 0;
}
// 0, 0, 0, 1
ので受け取った auto
の変数を decltype
に使うことができる
// ???
#include <type_traits>
#include <stdio.h>
#include <string.h>
int main() {
const char* p = "TEST";
auto c = *p;
decltype(c) b[256];
return puts(strcpy(b, p));
}
// TEST