環境
Microsoft Visual Studio Professional 2012
参考
C++11の新機能のうち便利そうなものを自分用にメモる ※この記事の抜粋になってしまった
std::bind
スマートポインタ
std::unique_ptr, std::shared_ptr 等が追加。
boostを使う必要なし。
#include <memory>
class SmartPtr
{
public:
SmartPtr()
{
std::cout << "new SmartPtr" << std::endl;
}
~SmartPtr()
{
std::cout << "delete SmartPtr" << std::endl;
}
};
// スマートポインタ
{
std::unique_ptr<SmartPtr> sp;
sp.reset(new SmartPtr()); // new SmartPtr
} // delete SmartPtr
enum class
enum名::enum項目名 みたいな使い方ができる。
#include <cstdint> // std::uint32_t のため
enum class EnumTest : std::uint32_t
{
Enum1 = 123,
Enum2,
};
{
EnumTest e = EnumTest::Enum1;
if (e == EnumTest::Enum1)
{
}
}
コンテナ
std::unordered_map, std::unordered_set, std::array 等が追加。
boostを使う必要なし。
#include <array>
{
std::array<int, 10> ar = {};
ar.fill(5); // 全ての要素を5で埋める。
for (auto const &a : ar) // for については後述。
{
std::cout << a << std::endl; // 5/5/5/5/...
}
}
for
逆順はないみたい。
その分まだboost/foreach.hppを使う方がいいかも。
#include <string>
#include <vector>
#include <unordered_map>
{
// コンテナに対してイテレーションする
std::vector<std::string> vec;
vec.push_back("first");
vec.push_back("second");
for (auto const &v : vec)
{
std::cout << v << std::endl; // first/second
}
// マップ
std::unordered_map<int, std::string> map;
map[-10] = "minus 10";
map[ 32] = "plus 32";
// v.first/v.second でアクセス
for (auto const &v : map)
{
std::cout << "[" << v.first << "] : " << v.second << std::endl; // [-10] : minus10/[32] : plus 32
}
std::begin, std::end
STLコンテナ以外にも使用できる。
#include <iostream>
#include <algorithm>
{
int arr[12] = {1,2,3,4,5,6,7,8,9,10,11,12};
std::cout << "for : ";
for (auto a : arr)
{
std::cout << a << ","; // for : 1,2,3,4,5,6,7,8,9,10,11,12
}
std::cout << std::endl;
// std::begin/std::end
int* p = std::find(std::begin(arr), std::end(arr), 3);
if (p != std::end(arr))
{
std::cout << "find : " << *p << std::endl; // find : 3
}
std::fill(std::begin(arr), std::end(arr), 256);
std::cout << "fill : ";
for (auto a : arr)
{
std::cout << a << ","; // fill : 256,256,...256,
}
std::cout << std::endl;
}
nullptr
NULLではなくnullptrを使う。
型推論
auto や decltype で型を自動判定する。
関数でもいける。
float getFloat()
{
return 1.53f;
}
{
// decltype
decltype(getFloat()) d = getFloat();
std::cout << "decltype(getFloat()) d is " << d << std::endl; // decltype(getFloat()) d is 1.53
// auto
auto dd = d;
const auto& myprintf = printf;
myprintf("myprintf %f\n", dd); // myprintf 1.530000
}
static assert
同じくboostを使わないでよくなった。
{
static const int test[] =
{
0, 1, 2, 3,
};
// NG
//static_assert((sizeof(test)/sizeof(int)) == 3, "test is invalid size.");
// OK
static_assert((sizeof(test)/sizeof(int)) == 4, "test is invalid size.");
}
ラムダ式
auto と組み合わせて使いやすくなった気がする。
{
int z = 2;
auto func1 = [](int x) {
return x * x;
};
auto func2 = [&z](int x) {
int ret = z*x;
--z;
return ret;
};
std::cout << "func1() = " << func1(3) << std::endl; // func1() = 9
std::cout << "func2() = " << func2(3) << std::endl; // func2() = 6
std::cout << "z = " << z << std::endl; // z = 1
}
std::function, std::bind
もともとあったと思うんだけど、使いやすくなった。
boost::bind とかは使う必要なくなった。
#include <functional>
class LumdaFunc
{
public:
LumdaFunc() : member(0), func() {};
~LumdaFunc() {};
void make(int x)
{
member = x;
auto f = [this]() {
std::cout << "member is " << member << std::endl;
};
func = f;
}
void call()
{
func();
}
private:
int member;
std::function<void ()> func;
};
class BindMethod
{
public:
BindMethod(int m) : member(m) {};
~BindMethod() {};
void bindMethod(int x)
{
std::cout << "bindMethod : " << member << ", and next is " << x << std::endl;
member = x;
}
private:
int member;
};
int bindFunc(int x, int y, int& z)
{
++z;
std::cout << "x is " << x << ", y is " << y << std::endl;
return z;
}
{
LumdaFunc lf;
lf.make(3);
lf.call(); // member is 3
// bind
int opt = 32;
auto f1 = std::bind(bindFunc, std::placeholders::_1, std::placeholders::_2, std::ref(opt));
f1(1,2); // x is 1, y is 2
std::cout << "after f1(1,2), opt is " << opt << std::endl; // after f1(1,2), opt is 33
// クラスのメソッドに bind
BindMethod bm(512);
auto f2 = std::bind(&BindMethod::bindMethod, bm, std::placeholders::_1);
f2(1024); // bindMethod : 512, and next is 1024
f2(2048); // bindMethod : 1024, and next is 2048
}
コード全体
#include <memory>
#include <array>
#include <functional>
#include <string>
#include <vector>
#include <unordered_map>
#include <cstdint>
#include <iostream>
namespace
{
// スマートポインタ
class SmartPtr
{
public:
SmartPtr()
{
std::cout << "new SmartPtr" << std::endl;
}
~SmartPtr()
{
std::cout << "delete SmartPtr" << std::endl;
}
};
// enum class
enum class EnumTest : std::uint32_t
{
Enum1 = 123,
Enum2,
};
// decltype
float getFloat()
{
return 1.53f;
}
// override
class Base
{
public:
Base() : member(0) {};
virtual ~Base() {};
virtual void setBase(int a)
{
member = a;
}
private:
int member;
};
class Inherited : public Base
{
public:
Inherited() : Base(), inherited_member(0) {};
~Inherited() {};
virtual void setBase(int a) override
{
inherited_member = a;
}
private:
int inherited_member;
};
// lumda/function
class LumdaFunc
{
public:
LumdaFunc() : member(0), func() {};
~LumdaFunc() {};
void make(int x)
{
member = x;
auto f = [this]() {
std::cout << "member is " << member << std::endl;
};
func = f;
}
void call()
{
func();
}
private:
int member;
std::function<void ()> func;
};
// function
class BindMethod
{
public:
BindMethod(int m) : member(m) {};
~BindMethod() {};
void bindMethod(int x)
{
std::cout << "bindMethod : " << member << ", and next is " << x << std::endl;
member = x;
}
private:
int member;
};
int bindFunc(int x, int y, int& z)
{
++z;
std::cout << "x is " << x << ", y is " << y << std::endl;
return z;
}
}
int main()
{
// 開始
std::cout << "cpp11 test." << std::endl;
// スマートポインタ
{
std::unique_ptr<SmartPtr> sp;
sp.reset(new SmartPtr());
}
// enum class
{
EnumTest e = EnumTest::Enum1;
if (e == EnumTest::Enum1)
{
std::cout << "enum1 " << static_cast<std::uint32_t>(EnumTest::Enum1) << std::endl;
std::cout << "enum2 " << static_cast<std::uint32_t>(EnumTest::Enum2) << std::endl;
}
}
// array
{
std::array<int, 10> ar = {};
ar.fill(5);
for (auto const &a : ar)
{
std::cout << a << std::endl;
}
}
// for
{
std::vector<std::string> vec;
vec.push_back("first");
vec.push_back("second");
for (auto const &v : vec)
{
std::cout << v << std::endl;
}
// マップ
std::unordered_map<int, std::string> map;
map[-10] = "minus 10";
map[ 32] = "plus 32";
for (auto const &v : map)
{
std::cout << "[" << v.first << "] : " << v.second << std::endl;
}
}
// 型推論
{
// decltype
decltype(getFloat()) d = getFloat();
std::cout << "decltype(getFloat()) d is " << d << std::endl;
// auto
auto dd = d;
const auto& myprintf = printf;
myprintf("myprintf %f\n", dd);
}
// static assert
{
static const int test[] =
{
0, 1, 2, 3,
};
// NG
//static_assert((sizeof(test)/sizeof(int)) == 3, "test is invalid size.");
// OK
static_assert((sizeof(test)/sizeof(int)) == 4, "test is invalid size.");
}
// lumda
{
int z = 2;
auto func1 = [](int x) {
return x * x;
};
auto func2 = [&z](int x) {
int ret = z*x;
--z;
return ret;
};
std::cout << "func1() = " << func1(3) << std::endl;
std::cout << "func2() = " << func2(3) << std::endl;
std::cout << "z = " << z << std::endl;
}
// function
{
LumdaFunc lf;
lf.make(3);
lf.call();
// bind
int opt = 32;
auto f1 = std::bind(bindFunc, std::placeholders::_1, std::placeholders::_2, std::ref(opt));
f1(1,2);
std::cout << "after f1(1,2), opt is " << opt << std::endl;
// クラスのメソッドに bind
BindMethod bm(512);
auto f2 = std::bind(&BindMethod::bindMethod, bm, std::placeholders::_1);
f2(1024);
f2(2048);
}
// 終了
std::cin.get();
return 0;
}
出力
cpp11 test.
new SmartPtr
delete SmartPtr
enum1 123
enum2 124
5
5
5
5
5
5
5
5
5
5
first
second
[-10] : minus 10
[32] : plus 32
decltype(getFloat()) d is 1.53
myprintf 1.530000
func1() = 9
func2() = 6
z = 1
member is 3
x is 1, y is 2
after f1(1,2), opt is 33
bindMethod : 512, and next is 1024
bindMethod : 1024, and next is 2048