ぬの部屋(仮)
nu-no-he-ya
  •      12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • libzipを試す(展開)

    以下は、zipファイル内の三番目(index==2)のファイルを展開するプログラム。

    コード

    #include <zip.h>
    
    #include <iostream>
    
    #pragma comment(lib,"zip.lib")
    
    int main(int argc, char* argv[])
    {
      // ZIPファイルを読み取り専用で開く
      int errorp;
    
      zip_t* zipper = zip_open(R"(C:\test\zipdata.zip)", ZIP_RDONLY , &errorp);
    
      // ZIP内のファイルの個数を取得
      zip_int64_t num_entries = zip_get_num_entries(zipper, 0);
    
      // ZIP内のファイルの各ファイル名を取得
      std::cout << "count: " << num_entries << std::endl;
      for (zip_int64_t index = 0; index < num_entries; index++) {
        std::cout << "[" << index << "]" << zip_get_name(zipper, index, ZIP_FL_ENC_RAW) << std::endl;
      }
    
      // ZIP内の2番目のファイルに関する情報を取得する
      struct zip_stat sb;
      zip_int64_t index = 2;
      zip_stat_index(zipper, index, 0, &sb);
    
      // 2番目のファイルのファイルサイズと同じメモリを確保する
      char* contents = new char[sb.size];
    
      // 2番目のファイルの内容をメモリに読み込む
      zip_file* zf = zip_fopen(zipper, sb.name, 0);
      zip_fread(zf, contents, sb.size);
      zip_fclose(zf);
    
      zip_close(zipper);
      //////////////////
      // ファイル名を出力できる形に変更
      // ファイル一覧は階層構造をしておらず、ディレクトリ区切りは'/'で直接出力できないので
      // ファイル名中の'/'を'-'に置き換える。
      // 本来なら再帰的にディレクトリを作るなどすべき。
      std::string target = sb.name;
      for (size_t i = 0; i < target.size(); i++) {
        if (target[i] == '/') {
          target[i] = '-';
        }
      }
      //
      //////////////////
      // 解凍したファイルを作成
      std::string outname = R"(C:\test\)" + target;
      FILE* of = fopen(outname.c_str(), "wb");
      fwrite(contents, 1, sb.size, of);
      fclose(of);
      int i;
      std::cin >> i;
    }
    

    ファイルの構造

    実行結果

    表示

    ファイル

    libzipを試す (圧縮)

    #include <zip.h>
    
    #pragma comment(lib,"zip.lib")
    
    
    int main(int argc, char* argv[])
    {
    
      int errorp;
      zip_t* zipper = zip_open(R"(C:\dev\out.zip)", ZIP_CREATE | ZIP_EXCL, &errorp);
    
      zip_source_t* source;
    
      try {
        /////////////////////////////////////////////////////////////////////
        /////////////////////////////////////////////////////////////////////
        // ファイル追加
    
        source = zip_source_file(zipper, R"(C:\test\data\img1.jpg)", 0, 0);
        if (zip_file_add(zipper, R"(img1.jpg)", source, ZIP_FL_ENC_UTF_8) < 0) {
          //エラー処理
          zip_source_free(source);
          throw 1;
        }
        source = zip_source_file(zipper, R"(C:\test\data\img2.jpg)", 0, 0);
        if (zip_file_add(zipper, R"(img2.jpg)", source, ZIP_FL_ENC_UTF_8) < 0) {
          //エラー処理
          zip_source_free(source);
          throw 1;
        }
        source = zip_source_file(zipper, R"(C:\test\data\img3.jpg)", 0, 0);
        if (zip_file_add(zipper, R"(img3.jpg)", source, ZIP_FL_ENC_UTF_8) < 0) {
          //エラー処理
          zip_source_free(source);
          throw 1;
        }
    
        /////////////////////////////////////////////////////////////////////
        /////////////////////////////////////////////////////////////////////
        // ディレクトリ追加
        if (zip_dir_add(zipper, "folder", ZIP_FL_ENC_UTF_8) < 0) {
          //エラー処理
          zip_source_free(source);
          throw 1;
        }
    
        /////////////////////////////////////////////////////////////////////
        /////////////////////////////////////////////////////////////////////
        // ファイル追加
    
        source = zip_source_file(zipper, R"(C:\test\data\dir\img4.jpg)", 0, 0);
        if (zip_file_add(zipper, R"(folder\img4.jpg)", source, ZIP_FL_ENC_UTF_8) < 0) {
          //エラー処理
          zip_source_free(source);
          throw 1;
        }
        source = zip_source_file(zipper, R"(C:\test\data\dir\img5.jpg)", 0, 0);
        if (zip_file_add(zipper, R"(folder\img5.jpg)", source, ZIP_FL_ENC_UTF_8) < 0) {
          //エラー処理
          zip_source_free(source);
          throw 1;
        }
        source = zip_source_file(zipper, R"(C:\test\data\dir\img6.jpg)", 0, 0);
        if (zip_file_add(zipper, R"(folder\img6.jpg)", source, ZIP_FL_ENC_UTF_8) < 0) {
          //エラー処理
          zip_source_free(source);
          throw 1;
        }
    
        zip_close(zipper);
    
      }
      catch (...) {
        zip_close(zipper);
      }
    
      return 0;
    }
    

    元データ

    圧縮後

    libzipを試す(CMakeビルド)

    zlibについて

    libzipのビルドにはzlibが必要。

    libpngをやったときのzlibを使いまわすのでこの点は省略する。

    libzipのCMake

    まずConfigureすると、以下のようにエラーが出る。

    とりあえずzlibのパスとインストール先を指定する。

    この状態でConfigureすると、以下のようにBZIP2とLIBLZMAでWarningが出るが、support disabledと言われているだけなので無視してGenerateしてOpen Projectする。

    Open ProjectしたらReleaseにしてALL BUILDしてINSTALLする。

    所感

    そもそもなんでlibzipをやろうと思ったかというと、今まで勝手にzlibがzipファイル作成ライブラリだと思い込んでいて、libpng関連でzlibについて調べて初めて真相を知ったから。

    あと、次回はサンプルコードを書く。

    Daz Importer version 1.4 を試す

    DAZ のシーンを Blenderに読み込むアドオン。

    今回使用した環境

    Blender 2.82   ,   DAZ 4.12

    公式

    Diffeomorphic

    http://diffeomorphic.blogspot.com/p/daz-importer-version-14.html

    お断り

    私はモデリングやレンダリングに関してはライト層なのでcatとsheepがとりあえず出てくればいいや程度の判断しかしておらず、他のアドオンより優れていると判断して扱っているわけではないのでその点を踏まえてください。

    インストール~読み込み

    インストールマニュアルがもの凄く親切に画像を載せて書かれているので殆どここを読めばできる。

    http://diffeomorphic.blogspot.com/p/daz-importer-version-14.html

    0.zipをダウンロード・展開
    1.Blender 側のアドオンをインストール・設定
    2.DAZ Studio 側のアドオンをインストール
    3.DAZ library pathの設定(いらない)

    4.DAZで普通に.dufファイルを保存,アドオンで同名の.jsonファイルを出力
    5.Blender側で読込

    インストール手順

    0.ダウンロード

    ダウンロードリンクをクリックした先はDropboxなのでその辺にあるダウンロードボタンを押してダウンロードする。

    1.Blender 側のアドオンをインストール・設定

    インストールはマニュアルそのままでいい。
    http://diffeomorphic.blogspot.com/p/installing-blender-add-on.html

    要約:「Edit->Preferenceからadd-onsのInstallでダウンロードしたzipをそのまま指定してチェックもいれちゃってください」

    設定もおそらくは基本そのままでいいはずだがエラーが出たら下参照。

    Blender側の設定で最も重要なことは「DAZのフィギュアデータが入っているディレクトリを指定する事」で、使ってみてファイルが見つかりませんのようなエラーが出た場合まずここを疑うべき。

    2.DAZ Studio 側のアドオンをインストール・設定

    これも公式そのままでいい。

    http://diffeomorphic.blogspot.com/p/installing-daz-studio-plugin.html

    3.Setting up DAZ library paths

    基本やらなくていい。

    使用方法

    4.DAZからファイルを出力 (duf形式),jsonファイルを出力

    duf出力

    DAZで普通にフィギュアを設定し、

    [File]→[Save]

    で.dufファイルを保存

    json出力

    今回新しく入れたアドオンで、dufファイルと同じ場所に.jsonファイルを出力する。ファイル名部分はdufファイルと同じである必要がある。

    [File]→[Export Basic Data]

    5.Blender側で読み込み

    [File]→[Import]→[DAZ Native]

    または、以下Import DAZ Fileからdufファイルを読み込む

    インポート結果

    トラブル

    ファイルが見つからないとエラーが出る場合がある。以下エラーログ:

    MISSING ASSETS:
    /data/daz%203d/genesis%202/female/genesis2female.dsf
    /data/daz%203d/genesis%202/female/genesis2female.dsf
    /data/daz%203d/genesis%202/female/genesis2female.dsf
    /data/daz%203d/genesis%202/female/genesis2female.dsf
    /data/daz%203d/genesis%202/female/genesis2female.dsf

    私の場合、フィギュアのフォルダ構成が

    \DAZ 3D\Studio\My Daz Connect Library\data\cloud\1_16280\data\daz 3d\genesis 2\female\genesis2female.dsf

    のような状態になっていたからで、特に赤字部分はDAZコネクトによりインストールすることで勝手に決められてしまう。Daz Importer 1.4ではディレクトリが9個しか(?)登録できないこともあり、これを全部登録するのは無理がある。

    \data\  以下の青時部分は共通しているので、\cloud\(数字)\ より下の内容を全部他の場所に固めてコピーし、そのディレクトリを指定すれば動くようにはなる。

    今後のことも考えればDAZコネクト使用時のディレクトリをわかりやすいものにする方法を探すべき。

    だが見つからなかったので、DAZ Install Managerからインストールしなおした。

    DAZ Install Manager からダウンロードした場合、格納先はBasic Settings…から確認できる。そして多分デフォルトでインストールしたならこのパスはBlenderのaddon側に既に入っていると思うので変える必要はない(かもしれないが確認したほうがいい)

    参考:(DAZ コネクトについて)
    http://kotozone.blog55.fc2.com/blog-entry-392.html

    猫と羊

    graphvizを使ってみる

    download

    公式の一番目立つダウンロードを押しても少なくともWindows版はよくわからないところに飛ばされるので以下からダウンロードする

    https://graphviz.gitlab.io/_pages/Download/Download_windows.html

    dotファイルを作成(sample.dot)

    
    graph g{
        node[
            fontname="MS Gothic"
        ]
    
        "いろは" -- "にほへと" -- "ちりぬるを";
    }
        

    日本語を表示する場合、fontnameに日本語フォントを指定する必要がある。

    コマンド

    \release\bin\dot.exe をコマンドプロンプトから実行する

    >dot -Tpng C:\test\gra\sample.dot -o a.png

    ここで赤字は出力形式。当然だが出力はカレントディレクトリなのでパスを通さず上記を実行するとdot.exeと同じ場所にa.pngが生成される。

    出力形式一覧

    https://graphviz.org/doc/info/output.html

    単純な線でつなげた例

    graph g{
        node[
            fontname="MS Gothic"
        ]
    
        "いろは" -- "にほへと" -- "ちりぬるを";
    }
    

    矢印

    矢印には digraphを使う

    
    digraph g{
        node[
            fontname="MS Gothic"
        ]
    
        "いろは" -> "にほへと" -> "ちりぬるを";
        "いろは" -> "日本語";
        "日本語" -> "いろは";
    }
        

    ノードの塗りつぶし色

    digraph g{
        node[
            fontname="MS Gothic"
        ]
    
    //ノード定義
        "いろは"      [fillcolor=plum ,style=filled]
        "にほへと"    [fillcolor=cyan ,style=filled]
        "ちりぬるを"  [fillcolor=white,style=filled]
    
    
        "いろは" -> "にほへと";
        "いろは" -> "ちりぬるを";
    }
        

    色一覧
    http://www.graphviz.org/doc/info/colors.html

    エッジにラベル

    
    digraph g{
        node[ fontname="MS Gothic" ]
        edge[ fontname="MS Gothic" ]
    
    
        "いろは" -> "にほへと"   [label="連続"];
        "いろは" -> "ちりぬるを" [label="非連続"];
    }
        

    ノードの形状

    
    digraph g{
        node[ fontname="MS Gothic" ]
    
    //ノードの定義 "いろは" [shape=circle]; "にほへと" [shape=triangle]; "ちりぬるを" [shape=diamond] "いろは" -> "にほへと"; "いろは" -> "ちりぬるを"; }

    ノードの形状一覧:
    https://graphviz.gitlab.io/_pages/doc/info/shapes.html

    Blender 2.8 python textを追加

    import bpy
    
    

    # textオブジェクトの追加

    fontCurve1
    = bpy.data.curves.new(type="FONT",name="fontCurve1") obj = bpy.data.objects.new("textObject",fontCurve1) obj.data.body = "Hello"# textオブジェクトの内容 # 新しいCollrectionを作成 newCol = bpy.data.collections.new('Collection 1') # 現在のシーンにコレクションをリンク bpy.context.scene.collection.children.link(newCol) newCol.objects.link(obj)

    # フォントの変更

    fnt = bpy.data.fonts.load('C:\Windows\Fonts\HARNGTON.TTF') obj.data.font = fnt
     

    実行結果

    色々な型に対応できる関数を作る(5)double型以外に対応する

    すっかり忘れていたが今までのパターンではdouble型にしか対応していなかった。

    #pragma once
    
    //////////////////////////////////////////////////////
    //////////////////////////////////////////////////////
    // プライマリテンプレート
    template<typename T>
    struct GETTER;
    
    //////////////////////////////////////////////////////
    //////////////////////////////////////////////////////
    // 特殊化用の構造体
    
    //小文字 x,y,z用特殊化用の構造体
    template<typename T>
    struct access_xyz {
      using scalar_t = decltype(T::x);
      static inline scalar_t& X(T& v) { return v.x; }
      static inline scalar_t& Y(T& v) { return v.y; }
      static inline scalar_t& Z(T& v) { return v.z; }
      static inline const scalar_t& X(const T& v) { return v.x; }
      static inline const scalar_t& Y(const T& v) { return v.y; }
      static inline const scalar_t& Z(const T& v) { return v.z; }
    };
    
    //大文字 X,Y,Z用特殊化用の構造体
    template<typename T>
    struct access_XYZ {
      using scalar_t = decltype(T::X);
      static inline scalar_t& X(T& v) { return v.X; }
      static inline scalar_t& Y(T& v) { return v.Y; }
      static inline scalar_t& Z(T& v) { return v.Z; }
      static inline const scalar_t& X(const T& v) { return v.X; }
      static inline const scalar_t& Y(const T& v) { return v.Y; }
      static inline const scalar_t& Z(const T& v) { return v.Z; }
    };
    
    //配列用特殊化用の構造体
    template<typename U,typename T>
    struct access_ARRAY{
      static inline U& X(T& v) { return v[0]; }
      static inline U& Y(T& v) { return v[1]; }
      static inline U& Z(T& v) { return v[2]; }
      static inline const U& X(const T& v) { return v[0]; }
      static inline const U& Y(const T& v) { return v[1]; }
      static inline const U& Z(const T& v) { return v[2]; }
    };
    
    //////////////////////////////////////////////////////
    //////////////////////////////////////////////////////
    // データ型(サンプル)
    // 型1
    struct vec_t {
      double x, y, z;
    };
    
    // 型2
    struct VEC_t {
      double X, Y, Z;
    };
    
    //////////////////////////////////////////////////////
    //////////////////////////////////////////////////////
    //特殊化1(デフォルトの型)
    
    template<>
    struct GETTER<vec_t> :public access_xyz<vec_t> {};
    
    template<>
    struct GETTER<VEC_t> :public access_XYZ<VEC_t> {};
    
    //////////////////////////////////////////////////////
    //////////////////////////////////////////////////////
    // 特殊化2(ポインタ版)
    
    template<typename T>
    struct GETTER<T*> : public access_ARRAY<T,T*> {};
    
    template<class T, std::size_t N>
    struct GETTER<T[N]> : public access_ARRAY<T, T[N]> {};
    
    template<typename T, std::size_t N>
    struct GETTER<std::array<T, N> > : public access_ARRAY<T, std::array<T, N> > {};
    
    //////////////////////////////////////////////////////
    //////////////////////////////////////////////////////
    // 関数本体
    
    template<
      typename T,
      class G = GETTER<T>
    >
    double length(const T & v) {
    
      return
        sqrt(
          G::X(v) * G::X(v) +
          G::Y(v) * G::Y(v) +
          G::Z(v) * G::Z(v)
        );
    }
    
    template<
      typename T,
      class G = GETTER<T>
    >
    void normalize(T & v) {
    
      double L = length(v);
    
      G::X(v) = G::X(v) / L;
      G::Y(v) = G::Y(v) / L;
      G::Z(v) = G::Z(v) / L;
    
    }
    

    色々な型に対応できる関数を作る(4)特殊化を短くする(配列込み)

    前回、配列版の事を忘れていたので追加。

    len.hpp

    #pragma once
    
    //////////////////////////////////////////////////////
    //////////////////////////////////////////////////////
    // プライマリテンプレート
    template<typename T>
    struct GETTER;
    
    //////////////////////////////////////////////////////
    //////////////////////////////////////////////////////
    // 特殊化用の構造体
    
    
    //小文字 x,y,z用特殊化用の構造体 template<typename T> struct access_xyz { static inline double& X(T& v) { return v.x; } static inline double& Y(T& v) { return v.y; } static inline double& Z(T& v) { return v.z; } static inline const double& X(const T& v) { return v.x; } static inline const double& Y(const T& v) { return v.y; } static inline const double& Z(const T& v) { return v.z; } }; //大文字 X,Y,Z用特殊化用の構造体 template<typename T> struct access_XYZ { static inline double& X(T& v) { return v.X; } static inline double& Y(T& v) { return v.Y; } static inline double& Z(T& v) { return v.Z; } static inline const double& X(const T& v) { return v.X; } static inline const double& Y(const T& v) { return v.Y; } static inline const double& Z(const T& v) { return v.Z; } }; //配列用特殊化用の構造体 template<typename T> struct access_ARRAY{ static inline double& X(T& v) { return v[0]; } static inline double& Y(T& v) { return v[1]; } static inline double& Z(T& v) { return v[2]; } static inline const double& X(const T& v) { return v[0]; } static inline const double& Y(const T& v) { return v[1]; } static inline const double& Z(const T& v) { return v[2]; } };
    ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // データ型(サンプル)
    // 型1
    struct vec_t { double x, y, z; }; // 型2 struct VEC_t { double X, Y, Z; };
     
    ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// //特殊化1(デフォルトの型) template<> struct GETTER<vec_t> :public access_xyz<vec_t> {}; template<> struct GETTER<VEC_t> :public access_XYZ<VEC_t> {}; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 特殊化2(ポインタ版) template<typename T> struct GETTER<T*> : public access_ARRAY<T*> {}; template<class T, std::size_t N> struct GETTER<T[N]> : public access_ARRAY<T[N]> {}; template<typename T, std::size_t N> struct GETTER<std::array<T, N> > : public access_ARRAY< std::array<T, N> > {};
    ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 関数本体 template< typename T, class G = GETTER<T> > double length(const T & v) { return sqrt( G::X(v) * G::X(v) + G::Y(v) * G::Y(v) + G::Z(v) * G::Z(v) ); } template< typename T, class G = GETTER<T> > void normalize(T & v) { double L = length(v); G::X(v) = G::X(v) / L; G::Y(v) = G::Y(v) / L; G::Z(v) = G::Z(v) / L; }

    main.cpp

    #include <iostream>
    #include <array>
    
    #include "len.hpp"
    
    
    ////エントリポイント
    int main()
    {
      double L;
      vec_t vv={ 1,1,1 };
      L = length(vv);
      std::cout << L << std::endl;
    
      double xyz[3] = { 1,1,1 };
      L = length(xyz);
      std::cout << L << std::endl;
    
      double* ptr = new double[3]{ 1,1,1 };
      L = length(ptr);
      std::cout << L << std::endl;
    
      std::array<double, 3> ary = { 1,1,1 };
      L = length(ary);
      std::cout << L << std::endl;
    
      int i;
      std::cin >> i;
    
    }
    

    色々な型に対応できる関数を作る(3)特殊化を短くする

    続き

    せっかくテンプレートを使用しているのに、GETTERの特殊化が長すぎる問題がある。

    今回はlength関数しか使用していないので特にそう感じる。x,y,zの要素をとる関数が、例えばinnner,outer,distance…等沢山あれば気にならない。

    とはいえ、短いほうがいいのは間違いないので、できる限り少ない行数で特殊化できないか考える。

    あらかじめ、要素がx,y,zの時に使えるaccess_xyzと、X,Y,Zの時に使えるaccess_XYZを用意しておく。

    #pragma once
    
    
    //////////////////////////////////////////////////////
    //////////////////////////////////////////////////////
    // プライマリテンプレート
    template<typename T>
    struct GETTER;
    
    ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // テンプレート
    template<typename T> struct access_xyz { using arg_t = T; using carg_t = const T; static inline double& X(arg_t& v) { return v.x; } static inline double& Y(arg_t& v) { return v.y; } static inline double& Z(arg_t& v) { return v.z; } static inline const double& X(carg_t& v) { return v.x; } static inline const double& Y(carg_t& v) { return v.y; } static inline const double& Z(carg_t& v) { return v.z; } };

    template<typename T> struct access_XYZ { using arg_t = T; using carg_t = const T; static inline double& X(arg_t& v) { return v.X; } static inline double& Y(arg_t& v) { return v.Y; } static inline double& Z(arg_t& v) { return v.Z; } static inline const double& X(carg_t& v) { return v.X; } static inline const double& Y(carg_t& v) { return v.Y; } static inline const double& Z(carg_t& v) { return v.Z; } };

    ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // ポインタ版 (変更なし) template<typename T> struct GETTER<T*> { using arg_t = T *; using carg_t = const T*; static inline double& X(arg_t v) { return v[0]; } static inline double& Y(arg_t v) { return v[1]; } static inline double& Z(arg_t v) { return v[2]; } static inline const double& X(carg_t v) { return v[0]; } static inline const double& Y(carg_t v) { return v[1]; } static inline const double& Z(carg_t v) { return v[2]; } }; template<class T, std::size_t N> struct GETTER<T[N]> { using arg_t = T[N]; using carg_t = const T[N]; static inline double& X(arg_t v) { return v[0]; } static inline double& Y(arg_t v) { return v[1]; } static inline double& Z(arg_t v) { return v[2]; } static inline const double& X(carg_t v) { return v[0]; } static inline const double& Y(carg_t v) { return v[1]; } static inline const double& Z(carg_t v) { return v[2]; } }; template<typename T, std::size_t N> struct GETTER<std::array<T, N> > { using arg_t = std::array<T, N> &; using carg_t = const std::array<T, N> &; static inline double& X(arg_t v) { return v[0]; } static inline double& Y(arg_t v) { return v[1]; } static inline double& Z(arg_t v) { return v[2]; } static inline const double& X(carg_t v) { return v[0]; } static inline const double& Y(carg_t v) { return v[1]; } static inline const double& Z(carg_t v) { return v[2]; } }; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 関数本体 template< typename T, class G = GETTER<T> > double length(const T & v) { return sqrt( G::X(v) * G::X(v) + G::Y(v) * G::Y(v) + G::Z(v) * G::Z(v) ); }

    使用例

    使用したい構造体に合わせて、継承元を変える。

    #include <array>
    
    #include "len.hpp"
    
    //////////////////////////////////////////////////////
    // 型1
    struct vec_t {
      double x, y, z;
    };
    
    //////////////////////////////////////////////////////
    // 型2
    struct VEC_t {
      double X, Y, Z;
    };
    
    
    //特殊化1
    template<>
    struct GETTER<vec_t> :public access_xyz<vec_t> {};
    
    //特殊化2 template<> struct GETTER<VEC_t> :public access_XYZ<VEC_t> {}; //エントリポイント int main() { double L; vec_t vv; vv.x = 1; vv.y = 1; vv.z = 1; L = length(vv); std::cout << L << std::endl; VEC_t VV; VV.X = 1; VV.Y = 1; VV.Z = 1; L = length(VV); std::cout << L << std::endl; int i; std::cin >> i; }

    色々な型に対応できる関数を作る(2)配列/ポインタ版

    前回の続き

    構造体が渡されたときとは別に、ポインタや配列が渡されたときも特殊化する必要がある。

    配列用の特殊化

    プライマリテンプレートが以下の時、

    //プライマリテンプレート
    template<typename T>
    struct GETTER;
    

    ポインタ、配列、std::arrayで別の特殊化が必要

    ポインタ版

    相手がポインタの場合、それを配列とみなすとする。


    特殊化は以下のようになる。

    template<typename T>
    struct GETTER<T*> {
      // ... 
    };
    

    配列版


    相手が配列の場合、ポインタとは別の特殊化が必要になる

    template<class T, std::size_t N>
    struct GETTER<T[N]> {
      // ...
    };
    

    std::array版


    相手がstd::arrayの場合の特殊化は以下

    template<typename T, std::size_t N>
    struct GETTER<std::array<T, N> > {
      // ...
    };
    

    実装例

    #include <type_traits>
    
    #include <array>
    
    #include "len.hpp"
    
    
    template<typename T> struct GETTER<T*> { using arg_t = T*; using carg_t = const T*; static inline double& X(arg_t v) { return v[0]; } static inline double& Y(arg_t v) { return v[1]; } static inline double& Z(arg_t v) { return v[2]; } static inline const double& X(carg_t v) { return v[0]; } static inline const double& Y(carg_t v) { return v[1]; } static inline const double& Z(carg_t v) { return v[2]; } };

    template<class T, std::size_t N> struct GETTER<T[N]> { using arg_t = T[N]; using carg_t = const T[N]; static inline double& X(arg_t v) { return v[0]; } static inline double& Y(arg_t v) { return v[1]; } static inline double& Z(arg_t v) { return v[2]; } static inline const double& X(carg_t v) { return v[0]; } static inline const double& Y(carg_t v) { return v[1]; } static inline const double& Z(carg_t v) { return v[2]; } };
     
    template<typename T, std::size_t N> struct GETTER<std::array<T, N> > { using arg_t = std::array<T, N> &; using carg_t = const std::array<T, N> &; static inline double& X(arg_t v) { return v[0]; } static inline double& Y(arg_t v) { return v[1]; } static inline double& Z(arg_t v) { return v[2]; } static inline const double& X(carg_t v) { return v[0]; } static inline const double& Y(carg_t v) { return v[1]; } static inline const double& Z(carg_t v) { return v[2]; } };

    //エントリポイント int main() { double L; vec_t vv; vv.x = 1; vv.y = 1; vv.z = 1; L = length(vv); std::cout << L << std::endl;
    //配列 double xyz[3]; xyz[0] = 1; xyz[1] = 1; xyz[2] = 1; L = length(xyz); std::cout << L << std::endl;

    //ポインタ double *pxyz = new double[3]; pxyz[0] = 1; pxyz[1] = 1; pxyz[2] = 1; L = length(pxyz); std::cout << L << std::endl;

    //std::array std::array<double, 3> ary; ary[0] = 1; ary[1] = 1; ary[2] = 1; L = length(ary); std::cout << L << std::endl;

    int i; std::cin >> i; }