69373


arduinoのコードについての質問です。

次のライブラリがあるとき

**Library.cpp**

[code]

    class library{
        public:
            enum hoge{
                A=0,
                B
                C
            };
            void func(hoge i);
    }
    
[/code]

loopの中でlibraryのfuncを使いたいのですが、

[code]

    library lib;
    
    void loop(){
        library::hoge huga = C;
        lib.func(fuga);
    }
    
[/code]

とすると `'fuga'was not decleard in this scope` となります。

どうにかしてlibraryのenumとfuncを使う書き方はありますでしょうか  
(できるだけライブラリ側に手をつけない方法で...)

追記：

[code]

    void loop(){
        //library::hoge huga = C;
        lib.func(lib.C);
    }
    
[/code]

という書き方はありますね。  
ただfuncの引数をABCそれぞれにしたい場合、別にintとかでインデックス指定してifをいちいち書くしかないのでしょうか...  
もっとスマートに書きたいですね...

[code]

    void loop(){
        //library::hoge huga = C;
        //lib.func(lib.C);
        FUNC(2);
        
    }
    void FUNC(int index){
        if(index == 0) lib.func(lib.A);
        else if(index == 1) lib.func(lib.B);
        else if(index == 2) lib.func(lib.C);
        return;
    }
    
[/code]


CC BY-SA 4.0
2020-08-08T08:19:26.333
69361
2020-08-08T23:58:54.540
2020-08-08T23:58:54.540
15413
41427
question
c++ arduino
ライブラリで定義されるenum型を外で使いたい


質問するときは環境に関する情報を詳しく記述しましょう。

  * [技術系メーリングリストで質問するときのパターン・ランゲージ](https://www.hyuki.com/writing/techask.html)

クラス（あるいは構造体）のブロック内で定義された従来のenumのメンバーは、`<クラス名>::<列挙定数名>`という形で参照します。

[code]

    class MyClass {
    public:
        enum InClassEnum {
            A, // 0
            B, // 1
            C, // 2
            InClassEnum_AllCount // 3
        };
        void func(InClassEnum val);
    };
    
    MyClass g_obj;
    
    void someGlobalFunc() {
        g_obj.func(MyClass::C);
    }
    
[/code]

C++11規格以降ではscoped
enumの構文が使えます。C++/CLIから逆輸入された構文ですが、こちらのほうがC#/Javaユーザーにとっては馴染みやすく、従来のenumよりも型安全なコードを記述しやすくなります。

[code]

    enum class MyScopedEnum {
        A,
        B,
        C,
    };
    
    MyScopedEnum val = MyScopedEnum::A;
    
[/code]

何を基準にして「スマート」だとしているのか、また最終的に何をしたいのかが具体的に分からないと答えようがありませんが、もし単純にすべての列挙定数のパターンを一様に処理したいということであれば、

  * 「enumメンバーの値が連続して増加する値である」ことが確実に保証される場合、ループカウンタの整数値から列挙型にキャストする方法があります。
  * 連続する値であることが保証されない場合、配列によるテーブルを作成してマッピングしてからループ処理する方法があります。

C/C++のenumでは、値を指定しなければ最初のメンバーには`0`が割り当てられ、以降は順番に値が1ずつ増えていきますが、個々のメンバーに値を明示的に指定して飛び飛びの値にすることもできます。  
ただしいずれにせよenumの実装に左右されるので、該当enumのメンバーが追加・変更された場合にはコードの修正が必要になることがあります。  
C++のenumには残念ながら、.NETの[`Enum.GetValues()`](https://docs.microsoft.com/en-
us/dotnet/api/system.enum.getvalues)メソッドや、Javaの`Enum.values()`メソッドに相当するものはありません。

[code]

    void someGlobalFunc1() {
        for (int i = 0; i < MyClass::InClassEnum_AllCount; ++i) {
            g_obj.func(static_cast<MyClass::InClassEnum>(i));
        }
    }
    
    void someGlobalFunc2() {
        const MyClass::InClassEnum table[] = {
            MyClass::A,
            MyClass::B,
            MyClass::C,
        };
        for (size_t i = 0; i < sizeof(table) / sizeof(*table); ++i) {
            g_obj.func(table[i]);
        }
    }
    
[/code]

ちなみにC++ではユーザー定義型の名前は大文字で始めることが推奨されています。また、すべて大文字の名前は慣例的にプリプロセッサマクロのシンボルに使用されることが多いので、少なくとも関数名や変数名をすべて大文字にするべきではありません。

  * [Stroustrup: C++ Style and Technique FAQ 日本語訳](http://www.libjingu.jp/trans/bs_faq2-j.html#Hungarian)


CC BY-SA 4.0
2020-08-08T18:32:18.480
69373
2020-08-08T18:32:18.480
15413
69361
answer