LoginSignup
6
8

More than 5 years have passed since last update.

VisualStudio2012 で使った方がよいC++11の機能

Last updated at Posted at 2016-10-26

環境

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
6
8
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8