7

次のコードはコンパイルされません。関数に渡され、構文が正しくないように見える配列のサイズを計算する方法を理解しようとしています。

私が得ているエラーは次のとおりです:

Error   1   error C2784: 'size_t getSize(T (&)[SIZE])' : could not deduce template argument for 'T (&)[SIZE]' from 'const byte []' 16   1 sizeofarray

ソースコードは次のとおりです。

#include <cstdint>
#include <stdio.h>

template<typename T, size_t SIZE>
size_t getSize(T (&)[SIZE]) {
    return SIZE;
}

typedef std::uint_fast8_t byte;

void processArray(const byte b[])
{
    size_t size = getSize(b); // <- line 16 where error occurs
    // do some other stuff
}

int main(const int argc, const char* argv[])
{
    byte b[] = {1,2,3,4,5,6};
    printf("%u\n", getSize(b));
    processArray(b);

    return 0;
}
4

4 に答える 4

9

これを機能させるには、processArrayもテンプレートにする必要があります。

template <size_t size>
void processArray(const byte (&b)[size])
{
    // do some other stuff
}

C ++では、配列を値で渡すことはできません。このような関数がある場合:

void f(int a[5]);

配列を値で渡しているように見えるかもしれませんが、言語には、この形式のパラメーターは別の言い方であるという特別な規則があります。

void f(int *a);

したがって、配列のサイズは型の一部ではありません。これはCから継承された動作です。幸い、C ++には参照があり、次のように配列への参照を渡すことができます。

void f(int (&a)[5]);

このようにして、配列のサイズが保持されます。

現在、残っている唯一のトリックは、関数をジェネリックにすることです。これにより、任意のサイズの配列で機能できるようになります。

template <size_t n> void f(int (&a)[n]);

これで、さまざまなサイズの配列を参照する関数の新しいバージョンを自動的に生成でき、テンプレートパラメーターを介してサイズにアクセスできます。

于 2012-11-12T15:17:06.190 に答える
6

関数の引数として、はとconst byte b[]同じように扱われconst byte *bます。関数が呼び出された配列のサイズに関するコンパイル時の情報はありません。

于 2012-11-12T15:15:15.463 に答える
5

processArray配列への参照を渡すには、テンプレートを作成して同じ手法を使用する必要があります。参照を渡さない場合、パラメーターはポインターであり、ポインター型には配列サイズ情報がありません。

template<size_t size>
void processArray(const byte (&b)[size]) {
    // ...
}
于 2012-11-12T15:17:21.627 に答える
-1

これは、配列サイズを決定するために、getSizeではなくのような関数テンプレートを使用する必要がある理由の標準的な例です。sizeof

  • を使用sizeofすると、ポインタのサイズを取得でき、賢明ではありません。
  • しかし、このようにすると、間違いを指摘するためのコンパイルエラーが発生します。

何が間違っていたのですか?それは関数パラメーターを持っていて、これは配列であるconst T arg[]ことを意味すると考えていました。argそうではありません。これはCの残念な構文であり、正確に。と同等ですconst T* argポインタを取得します。

これは、一部の人々が「配列はポインタである」と誤って考える理由でもあります。ではない。これはまさにこの特定の構文です。

于 2012-11-12T16:02:31.357 に答える