decltype
decltype(expression) で式の型を得ることができる。
利用シーン
- プロトタイプ宣言の型指定
- 関数の戻り値の型を得る
typeinfoを併用して使い方を見てみる。typeinfoは実行時型情報(RTTI RunTimeTypeIdentification)を取得する機能である。
また、C++のコンパイラが名前マングルした(シンボルがuniqueな名前となるように)文字列を閲覧するのではなく、デマングルして宣言した型であることを確認する。
libstdc++のcxxapi abi::__cxa_demangle()関数を利用する。
また、C++のコンパイラが名前マングルした(シンボルがuniqueな名前となるように)文字列を閲覧するのではなく、デマングルして宣言した型であることを確認する。
libstdc++のcxxapi abi::__cxa_demangle()関数を利用する。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// decltype.cpp | |
// CplusplusPractice | |
// | |
// Created by masai on 2015/04/10. | |
// Copyright (c) 2015年 masai. All rights reserved. | |
// | |
#include <iostream> | |
#include <vector> | |
#include <typeinfo> //オブジェクトの型を知るためのライブラリ | |
#include <cxxabi.h> | |
using namespace std; | |
int methoz(int i); | |
double methoz(double d); | |
struct B { | |
virtual ~B(){} | |
}; | |
struct D : B { | |
}; | |
//戻り値型が引数aに合わせて変化させたい | |
//Bの子であるDの場合も存在する | |
auto test(const B& a) -> decltype(a) { | |
cout << "typeid(a)=" << abi::__cxa_demangle(typeid(a).name(), 0, 0, 0) << endl; | |
return a; | |
} | |
int main(int argc, const char * argv[]) { | |
// methoz(1)の戻り値の型をもつ変数nを定義する | |
decltype(methoz(1)) n = 3.4; | |
// int型として出力される | |
cout << n << endl; | |
decltype(methoz(2.3)) m = 3.4; | |
// double型として出力される | |
cout << m << endl; | |
// 型によって異なるvectorをつくる | |
auto a = 10; | |
vector<decltype(a)> vec; | |
// int型として挿入される | |
vec.push_back(3.3); | |
vec.push_back(10); | |
for(int i = 0; i < vec.size(); ++i){ | |
cout << vec[i] << endl; | |
} | |
// 引数に合わせて戻り値が変化する関数 | |
B b_instance; | |
D d_instance; | |
cout << abi::__cxa_demangle(typeid(test).name(), 0, 0, 0) << endl; | |
test(b_instance); | |
test(d_instance); | |
return 0; | |
} |
type traits
型の特徴を調べたり、型の特徴を操作する関数C++11では、type_traitsをインポートして enable_if が使える。
template <bool B, Class T = void>enable_ifは、Bがtrueの時にtypedef T type;をもち、Bがfalseであればtypeをもたない。
struct enable_if;
SFINAE(Substitution Failure Is Not An Error)用途に使われる。
SFINAEは置き換え失敗はエラーにあらず、という意味で関数をオーバーライドする際、型変換がうまくいかなければオーバーライドの候補から自動ではずすことができる記述である。
ていうかいろんな書き方があってC++レベルが足りてない。以下の様な書き方があるってことを認識しておこう。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// typetraits.cpp | |
// CplusplusPractice | |
// | |
// Created by masai on 2015/05/19. | |
// Copyright (c) 2015年 masai. All rights reserved. | |
// | |
#include <iostream> | |
#include <type_traits> | |
// static_assertでコンパル時チェックを行うことが可能 | |
// enable_ifにtrueのみ渡すと、デフォルトのvoidの型になる | |
static_assert(std::is_same<std::enable_if<true>::type, void>::value, "::type"); | |
// enable_ifにtrueとintを渡すと、int型を返す | |
static_assert(std::is_same<std::enable_if<true, int>::type, int>::value, "::type"); | |
// enable_ifにtrueとunsignedを渡すと、unsigned型を返す | |
static_assert(std::is_same<std::enable_if<true, unsigned>::type, unsigned>::value, "::type"); | |
// enable_ifの第一引数にfalseを渡すと、type は無くなる | |
// ********************************************************************************** | |
// is_integralはTがint型かどうかを確認する | |
// 以下の記述方法はTがintでない場合には、funcの呼び出しをエラーとする | |
template<typename T> | |
void func(T x, typename std::enable_if<std::is_integral<T>::value>::type* =0){ | |
std::cout << "integral:" << x << std::endl; | |
} | |
// std::disable_if はないので、std::enable_if を使用する | |
template<typename T> | |
void func(T x, typename std::enable_if<!std::is_integral<T>::value>::type* =0){ | |
std::cout << "other:" << x << std::endl; | |
} | |
// ********************************************************************************** | |
// 以下は仮引数にenable_ifを記述しないタイプの書き方(enablerの利用) | |
// 条件無し。T は何型でもOKな関数f | |
template<class T> | |
void f(T const &){} | |
// T がint型と等しい時のみ有効な関数g | |
// is_integralはis_same<T, int>でも良い | |
extern void* enabler; // enabler | |
template<class T, typename std::enable_if<std::is_integral<T>::value>::type*& = enabler> | |
void g(T const &){ | |
} | |
// ********************************************************************************** | |
int main(int argc, const char * argv[]) { | |
// int型の変数a | |
int a = 0; | |
double d = 2.3; | |
// 構造体s | |
struct s{} b; | |
// func | |
func(a); | |
func(d); | |
f(a); // OK | |
f(b); // OK | |
g(a); // OK | |
//g(b); // gはint以外はエラーになる | |
return 0; | |
} |
0 件のコメント:
コメントを投稿