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