Rokiのチラ裏

学生による学習のログ

気になる内容メモ about C++1z #3

C++1zで気になる内容のメモ。スマホからの投稿。

static_assertのメッセージ省略

式を真であるか否かを確かめるだけの時にコンパイル時アサートを使う時、メッセージを一々書かなければならないのが面倒くさい。C++14まではマクロを用いて実質的な省略を実現していたが、C++1zではより規格的なコーディングで省略する事ができる。

下記はC++14。マクロを用いて、1st argumentsを文字列化したものをstatic_assertのメッセージとする事による実質的な省略。

#define STATIC_ASSERT(EXPR) static_assert(EXPR,#EXPR)
#define A 1
#define B 1

int main()
{
    constexpr unsigned int a=1;
    constexpr unsigned int b=1;

    STATIC_ASSERT(A==B);
    STATIC_ASSERT(a==b);
}

C++1z。より規格的なコーディング。

#define A 1
#define B 1

int main()
{
       constexpr unsigned int a=1;
       constexpr unsigned int b=1;

       static_assert(A==B);
       static_assert(a==b);
} 

様々なものが規格として成る事によって厳密化する事ができる。とても良い。

template template parameterにtypenameキーワードの使用を許可

template template parameterはC++14までclassキーワードしか使用できなかった。(コンパイラによってはサポートしていた)
C++1zではtypenameが規格的に使用できるようになる。

$ cat test.cpp
#include<vector>

template<template<class ...>typename Container>
struct A{Container<unsigned int> a;};

int main()
{
    A<std::vector> a;
}
$ g++ -std=c++0x test.cpp
test.cpp:3:29: error: template template parameter requires 'class' after the parameter list
template<template<class ...>typename Container>
                            ^~~~~~~~
                            class
1 error generated.

このエラー内容が許可されるようになる。(paiza.ioを使おうと思ったが、規格対応した時の事を踏まえて...)

値を返す型特性クラスのエイリアステンプレート

C++14まではf::typeと書かなければならなかったものが、スコープ解決済みのエイリアステンプレートが実装、追加されるため、f_t、またf::valueとしなければならなかったものがf_vと書く事ができ、スコープ解決を自前でする必要がなくなる。

C++14

#include<type_traits>
#define STATIC_ASSERT(EXPR) static_assert(EXPR,#EXPR)

int main()
{
    STATIC_ASSERT(std::is_array<int []>::value);
}

C++1z

#include<type_traits>

int main()
{
    static_assert(std::is_array_v<int []>);
}

個人的にはスコープ解決演算子を書いた方が明示的で視覚的に分かりやすい気がしないでもないが・・・。

std::begin、std::endのようなコンテナの要素情報にアクセスする非メンバ関数

自前の組み込み配列とコンテナを共通インタフェースで扱えるようにするため、std::empty、std::size、std::dataが実装されるとのこと。 iteratorヘッダで定義され、これらの関数は、constexpr関数として定義。これらの関数のうちコンテナ版は、戻り値の型がコンテナの定義に依存するためコンテナ内に定義されているメンバー関数に依存しているということになる。

C++14

#include<iostream>
#include<array>
#define SIZE(a) (sizeof(a)/sizeof(*(a)))

int main()
{
    std::array<unsigned int,5> ar{1,2,3,4,5,};
    unsigned int ar1[]{1,2,3,4,5,};

    for(unsigned int i=0; i<ar.size(); ++i)std::cout<<ar[i]<<std::endl;
    for(unsigned int i=0; i<SIZE(ar1); ++i)std::cout<<ar1[i]<<std::endl;
}

C++1z

#include<iostream>
#include<array>
#include<iterator>

int main()
{
    std::array<unsigned int,5> ar{1,2,3,4,5,};
    unsigned int ar1[]{1,2,3,4,5,};

    for(unsigned int i=0; i<std::size(ar); ++i)std::cout<<ar[i]<<std::endl;
    for(unsigned int i=0; i<std::size(ar1); ++i)std::cout<<ar1[i]<<std::endl;
}

ネストな名前空間の省略的記述法

// The name of a named namespace may be qualified.
namespace A::B { typedef int I; }
// is equivalent to:
namespace A { namespace B { typedef int I; } }

書いている間に時間なくなってしまったので取り敢えずアップする。細かい点は修正、追記していく予定。