LoginSignup
23
17

More than 5 years have passed since last update.

C++11、Arduinoでどこまで使えるの?

Last updated at Posted at 2017-05-13

この辺を参考にしてます。

現時点でArduino.appが1.8.2です。
いつのころからかC++11が使えるようになっているらしいです。
ただし、いろいろ便利なライブラリはついてないとか。

素のArduino.appでどこまで使えるのか、まあ、何か便利な機能はないかな?程度のノリですが、いろいろ試してみました。

ちなみに、いろいろなコンテナ関連、ポインタ関連の機能は、自分の理解と利用の範囲を超えるので試してません。あしからず。

autoによる型推論 : できる。ただし、配列にはできない。

auto x = 1.0;
auto y = 1;

みたいなことができます。右辺値から変数の型を推論するそうな。

ただし、配列で同じようにするとエラーに。

auto ary[] = {0,1,2,3};
/* エラー:
sketch_may02a:3: error: 'ary' declared as array of 'auto'
 auto ary[] = {0,1,2,3};
         ^
*/

配列にはこれまで通り int ARRAY_A[] = {1,2,3,4}; みたいな感じがいいようです。

Range-based for loop : 使える。

int ary[] = {1,2,3,4};

for (auto d: ary){
    //何らかの処理
}

みたいなことができます。
型はautoが使いやすいが、具体的なものでも問題ありません。
コピーコストが問題になる場合は、auto&& で参照するか、変更がないのであれば const auto& が使えるようです。

添字が必要な場合は、今まで通りか、要素が少なければ

const int RANGE[] = {0,1,2,3};

for (const auto& d: RANGE){
    //何らかの処理
}

みたいにするかな。

template : 使える。ただし、STLはない。

template<typename T>T add(T a, T b){
    return a + b;
  }

みたいなことができます。
ただしSTLがないので、いろいろ便利なコンテナの類は使えないようです。

戻り値を後置で宣言 : 使える。

//今まで
int add(int a, int b){
    return a + b;
};
//後置で宣言
auto add(int a,int b) -> int {
    return a + b;
};

上下同じことになります。ラムダ式と同じ見た目。なれれば見やすい?
後置の場合、->型名 は省略できません。
autoって書いてあるけど推論してくれない...

decltype : 使える

decltype(式)で式の型を返します。

auto add(int a,int b) -> decltype(a + b){
    return a + b;
};

で、戻り値の型を推論することができます。

上の三つをまとめると

template<typename T,typename U>auto add(T a, U b) ->decltype(a+b){
    return a + b;
  }

みたいなことができます。

ラムダ式 : 使える。ただし、関数の引数になれるが、戻り値にはなれない。

即時で使えるほか、auto変数で受けられます。

auto addF = [](const int& a, const int& b) -> int {return a + b;};

関数の引数にできます。

template<class F> int call2(F f) {
  return f(2);
}
auto f = [](int v) { return v + 3; };
auto a = call2(f);

ただし、ラムダ式に限らず、関数を返すことができないようです。

auto func() {
    int x = 0;
    return [=]()mutable -> int {
        return x++;
    };
}
/*エラー:
sketch_may02a:24: error: 'func' function uses 'auto' type specifier without trailing return type
 auto func() {
           ^
*/

構造体で関数オブジェクトを作って同じことしてみました。ちょっと無理矢理ですが...
やっぱりエラー。

auto Func(){
  struct {
    private:
    int i = 0;
    public:
    int operator()(){
      return i++;
    };
  } f ;
  return f;  
}
/*エラー:
sketch_may02a:39: error: cannot convert 'Func()::<anonymous struct>' to 'int' in return
   return f;  
          ^
*/

どちらのコードも、paiza.ioで試したらエラーは出ませんでした。

使いどころがむずかしい...
今まで通り、簡単なことは普通の関数で、複雑なことは関数オブジェクトでやると思います。

constexpr : 使える。

constexprは、keywordとしてはハイライトされないけれど、コンパイルは普通に通るようです。

constexpr unsigned int factorial(unsigned int x) {
    return x == 0 ? 1 : factorial(x - 1) * x;
}

使いどころがまだよくわかっていない...

{}による初期化 : 使えない。

auto b {1};
/*エラー
sketch_may02a:9: error: deducing from brace-enclosed initializer list requires #include <initializer_list>
 auto b {1};
          ^
*/

でもまあ、「初期化と代入は違うぞ」という気持を込めて

auto a (1);
int ary[] {1,2,3,4};

みたいな書き方にしようかと思います。

違ってるよ、とか、こんな便利な機能があるよ、というのがあればコメントおねがいします。

23
17
9

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
23
17