• 締切済み

固定長配列の参照に変換するoperator

固定長配列のラッパークラスを作っています。 以下のように固定長配列への参照に変換するoperatorを作りたいのですが、 かっこをどのようにつければいいのかわかりません。 同じ型のgetBuf関数を作ることはできました。 またtypedefを使えばできることはわかっていますが、使わない方法を知りたいです。 struct STRCONSTBUF{ char buf[2]; const char (&getBuf())[2]{ return buf; } //↓ここで構文エラー //getBufと同じ型のoperatorにしたい operator const char(&())[2]{ return buf; } }; 環境: Visual C++ 2008 Express よろしくお願いします。

みんなの回答

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

あ, 一応指摘しておきますが, 「getBuf の返り値の型」は const char (&)[2] なんだけど, 変換関数の opeartor のあとにこれをおくことは構文上できない, つまり直接指定することは不可能だと思います. & や * をこの位置に書けないっぽい.

haporu
質問者

お礼

返事が遅くなりすいません。 あきらめることにしました。 ありがとうございました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

decltype も std::identity も使えないということだと, typedef を使わなければならない ということでしょう.

haporu
質問者

お礼

ありがとうございます。 typedefにせずそのまま書きたかった理由は 1 IntelliSenseの入力候補に余計なtypedefメンバを表示したくない 2 クラスビューとオブジェクトブラウザに表示される型がわかりにくい 3 エラーメッセージに表示される型がわかりにくい なのですが、以下のようにすることでとりあえず1と3だけは解決できました。 template<typename T> struct TYPE{ typedef T Type; }; struct STRCONSTBUF{ char buf[2]; operator TYPE<const char[2]>::Type&(){ return buf + 0; } };

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

そのような operator の必要があるかどうかはよくわからんのだけど, できないんじゃないでしょうか. 「一見 typedef を使っていないように見える」だけでいいなら boost::mpl::identity を使えばできますが, boost::mpl::identity は内部で typedef を使っています. また, C++0x の decltype を使えば近いことはできますが, const を付けることができないような気がします. 逆にいえば「const を付けなくていい」なら可能で, 例えば struct Foo { char buf[2]; operator decltype((buf))() { return buf; } }; とするとこの変換関数は「char (&)[2]」への変換として機能します. 残念ながら const char (&)[2] への変換はできないのですが....

haporu
質問者

お礼

ありがとうございます。 VC++2010をインストールしたので試してみたいと思います。

haporu
質問者

補足

VC++2010で試してみた所、その構文は使えませんでした。 必要性については、operator const char*()にしてしまうと、 errno_t strcpy_s<_Size>(char(& _Dest)[_Size], const char * _Source) のような関数に渡すことができなくなってしまうからです。

  • hrsmmhr
  • ベストアンサー率36% (173/477)
回答No.1

ウル覚えなんですが… operator const char((*)()) ではないでしょうか?

haporu
質問者

お礼

ありがとうございます。 コンパイルエラーになってしまいました。

関連するQ&A

  • オペレータ定義について

    すみません、オペレータ定義について教えてください。 ■以下のようなクラスに、[] が定義されていて、 class String { public:       ・       ・ (メンバ関数がいくつかあり)       ・       // num 番目の文字を返す       char operator[](int num) const;       char& operator[](int num); private:       char* string; }; ■関数はこのように書かれていて、 char String::operator[](int num) const {     // 文字列の num 番目の文字を返す 1     return string[num]; } char& String::operator[](int num) {      // 文字列の num 番目の文字を返す 2      return string[num]; } ■これを →[] main() から使うにはどのようにしたらいいのでしょうか?

  • C#で構造体の配列を持った構造体を使いたいのですが

    C#で構造体の配列を持った構造体を使いたいのですが Cならば struct xyz { struct abc _abc[32]; int index; }; struct abc { int a; int b; int c; }; struct xyz _xyz[8]; xyz[0]._abc[3].b = 1; のような使い方で という感じで やっていた事を C#で 同じような事をやろうとしても うまくいきません うまくやる方法をどなたかご存知ないでしょうか Visual Studio 2005行った場合 コンパイルで 構文エラーです。不適切な配列の宣言子です。マネージ配列を宣言するには、次元指定子を変数の識別子の前に指定します。固定サイズ バッファ フィールドを宣言するには、フィールド型の前に fixed キーワードを使用します となり fixed をつけると 固定サイズ バッファの型は次のうちの 1 つでなければなりません: bool、byte、short、int、long、char、sbyte、ushort、uint、ulong、float または double となってしまいます

  • template 参照 operator について

    「ゲームプログラマになる前に覚えておきたい技術」という書籍を読みながらC++でプログラミングの学習をしているのですが、template class と 参照 と operator の組み合わさったクラスでわからないところがあります。 自分で出来る限り調べてみましたが、解決できなかったので、答えていただけると幸いです。 Cの学習はひととおり済んでおりますが、まだC++は学習を始めたばかりなので理解が浅いです。 質問内容にいたらない点があるとは思いますが、お願いします。 以下のようなクラス定義文がありました。 template< class T > class Array2D{ public: Array2D() : mArray( 0 ){} ~Array2D(){ delete[] mArray; mArray = 0; } void setSize( int size0, int size1 ){ mSize0 = size0; mSize1 = size1; mArray = new T[ size0 * size1 ]; } T& operator()( int index0, int index1 ){ return mArray[ index1 * mSize0 + index0 ]; } const T& operator()( int index0, int index1 ) const { return mArray[ index1 * mSize0 + index0 ]; } private: T* mArray; int mSize0; int mSize1; }; この定義文の以下の部分 T& operator()( int index0, int index1 ){ return mArray[ index1 * mSize0 + index0 ]; } において、T&という記述がなければ、()という演算子のはたらきを再定義していて、 mArrayを2次元的に利用できるように値を返しているように見えるのですが、 T&がつくことによって、なにがどうなっているのでしょうか。 それと、参照というのは、利用するときには必ず初期化が必要、と学習したのですが、 この場合、初期化の処理になっているのでしょうか。 今までに出てきた参照では、簡単な例でいうと int n; int& m = n; というように、型名&別名=参照先 と、即初期化して使っていました。 これなら初期化されているのはわかりますが、今回のように、 「別名」の部分がoperatorになっていると、どのアドレスが「別名」が指すアドレスになるのでしょうか。 さっぱりわかりません。 質問の連続になってしまって申し訳ありません。 ほんとに困ってます。 おねがいします。

  • 警告 : 問題のあるポインタの変換

    #include <iostream.h> char *f(){   char buf[1] = "\0"; // char *buf = "\0";  return static_cast<char*>(buf); } main(){  cout << f(); これで、関数の型が char * なのに、char [] 型変数を 返そうとするソースだからコンパイルで警告が出るんだと思いました。 関数の型が char [] なのに、char * 型変数を返したなら 返された値を変更できないから不都合が起こるのが 分かりますが、上に書いたソースの場合は不都合なことに なりますか? 問題のあるポインタの変換ということを言われるのが納得 できないので、納得させてください。

  • このプログラムのポインタを配列に変換したいんですけど

    C言語初心者です。助けてください。 途中までがんばったのですがどうしてもできません。問題はこの構造体の*name→name[25],*email→email[30]に変換させたいのですが、そのまま変換すると左辺値が必要や移植性のないポインタ変換などのエラーが出てしまいます。どうすればいいですか?教えてください。あと関数getlineと構造体は変えないでください。(指定した部分は除く) このプログラムは名前、メールアドレス、年齢を保存していき-1を入力した時出力されるというものです。 よろしくお願いします。 入力例 10 hakata abc@・・・ 12 yokohama dfg@・・・ -1 -1 -1 出力例 -1 -1 -1 12 yokohama dfg@・・・ 10 hakata abc@・・・ #include <stdio.h> #include<stdlib.h> struct node { char *name; char *email; int age; struct node *next; } heap[100], *hp = heap; void getline(char *s,int n) { int c; while(--n>0&&((c=getchar())!=EOF && c!='\n')) *s++=c; *s='\0'; } char* dupstr(char* strg) { char* newstr; newstr=(char*)malloc(sizeof(char)*strlen(strg)); strcpy(newstr,strg); return newstr; } struct node *new(int n ,char* a, char* b) { hp->age=n; hp->email=a; hp->name=b; hp->next=NULL; return hp++; } struct node *add(struct node *p, struct node *q) { q->next=p; p=q; return p ; } void print_list(struct node *p) { while (p != NULL) { printf("%d ", p->age); printf("%s ", p->name); printf("%s ", p->email); p=p->next; } printf("\n"); } main() { int age,p; char buf[80],a[80],b[80],*email,*name; struct node *root=NULL; while(getline!=NULL) { getline(buf,sizeof(buf)); age=atoi(buf); getline(b,sizeof(b)); getline(a,sizeof(a)); email=dupstr(b); name=dupstr(a); root=add(root,new(age,email,name)); if(age==-1) break; } print_list(root); }

  • 「互換でない型変換」というエラーが出てしまいます。

    ex.filのファイルの中身は以下の通りです。 0103 美空ひばり 川の流れのように 0209 山口百恵 いい日旅立ち 0992 キャンディーズ 危ない土曜日 このデータを構造体「iti」に読み込ませるために 以下のようにしました。 ------------------------ typedef struct itiran_ { char code[5]; char singer[20]; char melody[50]; } itiran; itiran iti; int main(void){ char buf[5]; char buf2[100]; ・ ・ ・ fp = fopen("ex.fil","r"); if(fp == NULL){ exit(1); } i = 0; while(fgets(buf2,sizeof buf2,fp) != NULL) iti[i].code = strtok(buf2," "); ↑ここでエラー iti[i].singer = strtok(NULL," "); iti[i].melody = strtok(NULL,"\n");i++; } ------------------------ 「iti[i].code = strtok(buf2," ");」のところで 「互換でない型変換」というエラーが出てしまいます。 iti[i].codeも buf2も どちらもchar型変数なのに どうしてこのようなエラーになるのかが 分かりません。 ご教示して頂けたら幸いです。

  • リンクエラーについて

    visual NET2003を使ってプログラムのコンパイルをしているんですが、 以下のようなエラーが出てしまって詰まっています。 すいませんが助言よろしくお願いします。 twcore.lib(twcore.obj) : error LNK2019: 未解決の外部シンボル "__declspec(dllimport) class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl std::operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,char const *)" (__imp_??6std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z) が関数 "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class TWOBJECT &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@AAVTWOBJECT@@@Z) で参照されました。 twstereorcv.exe : fatal error LNK1120: 外部参照 1 が未解決です。

  • C++のoperator関数でのキャストする場合の書き方がまだよく理解

    C++のoperator関数でのキャストする場合の書き方がまだよく理解できていません。 下記のコードで、 //ここから #include "stdafx.h" #include <string> #include <iostream> class AutoPtr { char *ptr; public: AutoPtr():ptr(0) { } ~AutoPtr() { delete [] ptr; } // char *operator=(char *ptr) { delete [] this->ptr; this->ptr = ptr; return this->ptr; } operator char *(){ return ptr; } char &operator[](int index) { return ptr[index]; } }; void reverse(char *str) { int i, n; AutoPtr work; n = strlen(str); work = new char[n+1]; strcpy(work, str); for(i=0; i<n; i++) { str[i] = work[n-i-1]; } printf("%s\n", str); } int _tmain(int argc, _TCHAR* argv[]) { char str[] = "ABCDEFG"; reverse(str); return 0; } //ここまで 2番目のoperator関数の定義ですが、 operator char *(){ return ptr; } これは多分、reverse()関数中の、 strcpy(work, str); のworkの展開に用いられると思うのですが、 機能としては、「operator char *」はAutoPtrをchar *にキャストするために使われているらしいのですが、何故この書き方でAutoPtrをchar *型にキャストできるのかがいまいち分かりません。また、2番目のoperator関数の記述「operator char *()」はどこまでが型で、どこからが関数の定義と見なせばよいのでしょうか? 何か勘違いしているかもしれません。理解されている方、御教示いただければと思っています。 よろしくお願い致します。

  • C++のクラス内での2次元配列

    C++学習者です。Windows 10上で、Visual Studio Community 2015 を使って勉強しています。 2次元配列を持つクラスを作ろうとしていますが、クラス定義ファイルの中のプライベート変数部分に2次元配列を定義しようとするとエラーメッセージが出てきます。 自分のソースコードは次のようなもので、最後の int aray[rowSize][colSize]; の部分に赤い波線が出ていて、そこにカーソルを合わせると「静的でないメンバー参照は特定のオブジェクトを基準とする相対参照である必要があります。」というメッセージが出ます。 #pragma once #ifndef DSUBARRAY_H // Double Subscripted Array #define DSUBARRAY_H #include <iostream> using namespace std; class DsubArray { public: friend ostream &operator<<(ostream &, const DsubArray &); // output array friend istream &operator>>(istream &, DsubArray &); // input array DsubArray(const int=1, const int=1); // default constructor DsubArray(DsubArray &); // copy constructor ~DsubArray(); // destructor int &operator()(int, int);// subscript -- lvalue const int &operator()(int, int) const; // subscript -- rvalue DsubArray &operator=(DsubArray &);// assignment bool operator==(DsubArray &) const; // equality check of the two arrays bool operator!=(DsubArray &) const; // inequality check int getRowSize() const; int getColSize() const; private: int rowSize; int colSize; int aray[rowSize][colSize]; }; #endif これをたとえば次のように書き換えると、赤い波線は消えるのですが、今度はコラムのサイズが10に固定されてしまい、コンストラクターでこれと異なる数値を与えるとエラーになってしまうのではないかと心配します。 int aray[ ][10]; どなたか2次元配列の正しい作り方を教えてください。お願いいたします。

  • 多次元配列の new 2

    追加の質問ですみません^^; char の8個の配列へのポインタの配列を new する場合などは、以下のサンプルのように typedef しないとかけないんでしょうかね?たとえば、  char (**bb)[8] = new (char (*)[8])[8]; 書きたいように思いますが、これは文法違反ですし・・・^^; ==== サンプル:(iostream の初期化時に、定義した new が呼び出されるかもしれないことを一応考慮して、stdio の関数を使っています^^) #include <new> #include <stdlib.h> #include <stdio.h> void *operator new(std::size_t s) { void *p = malloc(s); fprintf(stderr, "::new(): %p\t%lu\n", p, (unsigned long)s); return p; } void operator delete(void *p) { fprintf(stderr, "::delete(): %p\n", p); if (p) free(p); } void *operator new[](std::size_t s) { void *p = malloc(s); fprintf(stderr, "::new[](): %p\t%lu\n", p, (unsigned long)s); return p; } void operator delete[](void *p) { fprintf(stderr, "::delete[](): %p\n", p); if (p) free(p); } int main() { typedef char (*T)[8]; char (**b)[8] = new T[8]; delete[] b; } ==== % ./a.exe ::new[](): 0x6e01b0 32 ::delete[](): 0x6e01b0