1. ホーム
  2. c++

[解決済み] 引数リストに一致する関数テンプレートのインスタンスがない(配列を表示しようとした)。

2022-03-04 17:14:50

質問

これをコンパイルしようとすると

template<typename type,const char* format>__device__ void d_prettyPrintVector(type* v, const unsigned int size)
{
    printf("\n ");
    for(int i=0; i<size; i++)
            printf(format, v[i]);
}
template<> void d_prettyPrintVector<float, "%4.1f ">(float*, const    unsigned int);
template<> void d_prettyPrintVector<int,   "%2d "  >(int*,   const unsigned int);
template<> void d_prettyPrintVector<char,  "%2d "  >(char*,  const unsigned int);
template<> void d_prettyPrintVector<bool,  "%d"    >(bool*,  const unsigned int);

というように使用します。

d_prettyPrintVector(dc, blockDim.x);

私は

kernels.cu(104): error: no instance of function template "d_prettyPrintVector" matches the argument list
        argument types are: (int *, const unsigned int)

どうしたんですか?

解決方法は?

タイプの使い方が明確でないのでは? float , int などで、適切な書式文字列を取得します。

のような関数に作り替えることができます。

 template <typename type>
 void d_prettyPrintVector(type* v, const unsigned int size)
 {
    printf("\n");
    for(int i=0; i<size; i++)
            printf(getFormatString<type>(), v[i]);
                   // ^^^ Get an format string appropriate for the type.
 }

関数テンプレートがあれば、それは完全に有効なコードになります。

 template <typename type> char const* getFormatString();

は、あなたが興味を持っている型のための特殊化を持っていた。つまり、以下のようにすればよい。

 template <typename type> char const* getFormatString();

 template <typename type>
 void d_prettyPrintVector(type* v, const unsigned int size)
 {
    printf("\n");
    for(int i=0; i<size; i++)
            printf(getFormatString<type>(), v[i]);
                   // ^^^ Get an format string appropriate for the type.
 }

 template <> char const* getFormatString<float>() { return "%4.1f "; }
 template <> char const* getFormatString<int>()   { return "%2d "; }
 template <> char const* getFormatString<char>()  { return "%2d "; }
 template <> char const* getFormatString<bool>()  { return "%1d "; }

これで、使えるようになりました。

 int a[] = {1, 2};
 d_prettyPrintVector(a, 2);

 float b[] = {1.1f, 2.2f};
 d_prettyPrintVector(b, 2);

を問題なく実行できます。

おまけ

そのアイデアを拡張して、ラムダ関数を引数として d_prettyPrintVector . ラムダ関数は、単一のユースケースにより適したカスタムフォーマット文字列を返すことができます。

オーバーロード d_prettyPrintVector . ラムバ関数を引数に取ることができるものを用意する。

 template <typename type, typename Format>
 void d_prettyPrintVector(type* v, const unsigned int size, Format format)
 {
     printf("\n");
     for(int i=0; i<size; i++)
             printf(format(), v[i]);
}

新しい関数を使って初期関数を実装することもできるので、項目がどのように印刷されるかの詳細を繰り返す必要はありません。

template <typename type> char const* getFormatString();

template <typename type>
void d_prettyPrintVector(type* v, const unsigned int size)
{
   d_prettyPrintVector(v, size, [](){return getFormatString<type>();});
}

ここで、これまでのprintの呼び出しに加え ab が使えるようになりました。

   // Define the format on the fly, using a lambda function.
   d_prettyPrintVector(a, 2, []() -> char const* {return "%4d ";});

   // Define the format on the fly, using a lambda function.
   d_prettyPrintVector(b, 2, []() -> char const* {return "%.6f ";});