クラス内専用のfloat型の即値定数を宣言するには?

[戻る]
ビーバー 2013/05/20(月) 20:50:27
タイトルのお尋ねをさせて下さい。↓が例です。C++98以降のコンパイラで、どれも似た症
状でした。

class c
{
    static const float    f1 = 0.f; // 構文エラーになってしまうので、
    static const float    f2;       // これで試す。が即値定数にならない。↓が構文
エラーになる。
    static const int      i  = static_cast< int >( f1 * 3.f );
                                    // 構文エラー。f1が定数ではない、と言われる。
};
const float c::f2 = 0.f;

今の所、float型の即値定数を宣言するには、伝統的な #define を使うしかない、という状
況です。
が、もしかしたら私が知らないだけかもしれないと思い、質問させて頂きました。どうぞ宜
しくお願いします。

επιστημη [E-Mail] [HomePage] 2013/05/20(月) 21:15:47
VC++11(VS2012) で通りましたよ。



#include <iostream>



class c {

public:

  static const float f1;

};



const float c::f1 = 0.123f;



int main() {

  std::cout << c::f1 << std::endl;

}

tetrapod 2013/05/21(火) 09:07:24
「即値定数」という文言に何を期待しているか、で話は違うわけだが
・実行時に定数であることがわかっていればよい?
・コンパイル時に定数であることがわかっていて最適化される必要がある?

C++ 言語仕様書 ISO/IEC 14882:1998 9.4.2 static data member の 4
静的データメンバが const つき汎整数型または const つき列挙型の場合、
クラス定義内の静的データ宣言に <定数初期化子> を指定できる。
俺注釈:つまり汎整数型、列挙型以外は指定できないということ

ということで C++98 の範囲では
・ f1 f2 は定数メンバだが、その値をクラス内で与えることはできない。
 すなわち、実行時の定数ではあるがコンパイル時の定数ではない
・コンパイラが i を解釈する時点で f1 f2 の値はないので、これも通らない。

つまり C++98 の範囲では
・実行時定数は可能。
・コンパイル時定数は無理。

C++ 11 ISO/IEC 14882:2011 であれば(規格書買ってないので引用しないけど)
コンパイル時定数であることの明示 constexpr というキーワードが増えているので

class c {
 static constexpr float f1=12.3f;
 static const i=f1*10;
 int a[i];
}; 
とすることで、コンパイル時定数化が可能。

C++11 対応レベルの高いコンパイラは今のところ数が少なくて
gcc 4.7.x 以後
Visual Studio 2012 の VC++
くらいしか知らないなぁ

ホウジョウウサギ 2013/05/21(火) 09:15:24
問題が何なのかよくわかりませんが…
>static const int      i  = static_cast< int >( f1 * 3.f );
ここでf1の値が不明なのでエラーになる,ということだとすれば
素直に以下のようにすれば良いのではないでしょうか.

class c
{
public:
    static const float f1;
    static const int i;
};
const float c::f1 = 1.5f;
const int c::i = static_cast< int >(f1 * 3.0f);  //iの値はf1の値が定まった後に決める

仲澤@失業者 2013/05/21(火) 10:45:00
自分のコードを調べてみましたが、ホウジョウウサギさんと同じにしてますねぇ。
特にクラススタティックにこだわらなければ、ど〜せconstだし。

const float stf100    = 100f;
const int   stiiii  = static_cast< int >( stf100 * 3.f );

class c
{ 
  :
};

で、いいじゃん。というコードもありました(vv;)。

古いスレッドには追加発言できません。