Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
16
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

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

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

現時点で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};

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

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
16
Help us understand the problem. What are the problem?