2016-11-12 7 views
0

変更をテストしているときに私が見ていることを理解しようとしています。このプラットフォームはGCC 4.8でopenSUSE 42ですが、他の人に影響を与える可能性があります。テストコードとエラーが続きます。静的なクラス関数にconstを使用する必要があるのはなぜですか?

$ cat test.cxx 
#include <string> 

#if (__cplusplus >= 201103L) 
# define STATIC_CONSTEXPR static constexpr 
# define CONSTEXPR constexpr 
#else 
# define STATIC_CONSTEXPR static const 
# define CONSTEXPR 
#endif 

struct Name 
{ 
    STATIC_CONSTEXPR char* GetName() {return "XXX";} 
}; 

int main(int argc, char* arv[]) 
{ 
    const char* name = Name::GetName(); 
    return 0; 
} 

そして:

$ g++ -O3 -std=c++11 test.cxx -o test.exe 
test.cxx: In static member function ‘static constexpr char* Name::GetName()’: 
test.cxx:13:44: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] 
    STATIC_CONSTEXPR char* GetName() {return "XXX";} 
              ^

を追加することクリアされない:

struct Name 
{ 
    STATIC_CONSTEXPR char* const GetName() {return "XXX";} 
}; 

そして次を追加する明確にそれを行います。

struct Name 
{ 
    STATIC_CONSTEXPR const char* GetName() {return "XXX";} 
}; 
Does static constexpr variable make sense?による

すべての変数は、constexprのが暗黙的にconstのですが、constの静的な は、ほぼ直交していると宣言

は、私はほとんど私が思った(静的 constの整数との相互作用を除きます。)わかったconstexprしかし私は明らかに何かが(もう一度)不足しています。私が理解しているように、C++委員会は、実際に理解しているように、物理的な宇宙の法則では不可能であっても、ファイルが保存された後に何らかの形で変更することができると考えています("XXX")。しかし、問題を解決するために、彼らは私たちにconstexprを与えました。代わりの説明はhereですが、私はその違いを生む細かい詳細がわかりません。

なぜ警告が表示されるのですか。なぜ、それをスカルクするにはstatic constepr constが効果的に必要ですか?関数宣言に


$ uname -a 
Linux opensuse-42 4.1.27-27-default #1 SMP PREEMPT Fri Jul 15 12:46:41 UTC 2016 (84ae57e) x86_64 x86_64 x86_64 GNU/Linux 
opensuse-42:~$ gcc -v 
Using built-in specs. 
COLLECT_GCC=gcc 
COLLECT_LTO_WRAPPER=/usr/lib64/gcc/x86_64-suse-linux/4.8/lto-wrapper 
Target: x86_64-suse-linux 
Configured with: ../configure --prefix=/usr ... --host=x86_64-suse-linux 
Thread model: posix 
gcc version 4.8.5 (SUSE Linux) 
+4

いいえ、あなたは問題を理解していない:修正はどちらかです。 "再生器の中の" XXX "のような値は、ファイルが保存された後に何らかの形で変更することができます"とは何の関係もない無意味な声明です。リテラル文字列定数 "XXX"は 'const char *'であり、失敗したコードは 'char *'としてそれを返そうとします。定数オブジェクトへのポインタは、変更可能なオブジェクトへのポインタに暗黙的に変換することはできません。これは 'constexpr'とは関係ありません。 –

+0

'const char *'に代入するので、関数は 'const char *'を返す必要があります。 – Galik

+0

私は明確です... constexprとしてマークされた静的関数から返される値は暗黙的に 'const'ではありません。あれは正しいですか?これは、関数本体が '...(){STATIC_CONSTEXPR char val [] =" XXX ";戻り値。 } '? – jww

答えて

8

constexpr機能はconstexprなく、その戻り型であることを意味します。

だからあなたの問題は本当に、次の構文が間違っているに沸く:

char * foo = "bar"; 

char const[]からchar*にC++ 11この変換は違法出て平坦であり、C++ 98以降推奨されていませんので。

constへのポインタとは対照的に、ポインタをconstにすることは、より深く、hereを調べます。

文字列リテラルを返すには、char const*を使用する必要があります。 staticconstexprは、この問題にはまったく関係ありません。

+0

私の無知を許してください... 'contexpr'とマークされているが、const以外の値にできる変数や関数の戻り値の例は何ですか?つまり、発信者はそれを変更できます。私には意味がありません。彼らは直交しているようです。 – jww

+1

@jww 'constexpr'関数も非定数コンテキストで使うことができます。そのため、 'constexpr'関数がデフォルトで' const'を返さないようにすることが多分決定されたのです。そして、たとえ彼らが 'const'を返すとしても、あなた自身の場合、ポインター自体は' const * '(' char * const'のような)であって、それがポイントするデータではありません( 'char const *')。 – vsoftco

+0

ありがとう@krzaq。 C++ 11では 'static constexpr char * constexpr Name()'が必要ですか?外部の人によると、ファイルが保存された後も関数は変更されません。内側のものは、ファイルが保存された後も配列内のデータは変更されないと言いますか? – jww

3

文字列リテラー"..."は、const char[]のタイプ、つまりconst文字の配列です。必要に応じてconst char*に減衰することがあります。

const char*からchar*/char* constへの廃止予定の変換を使用しているため、警告が表示されます。関数がconstexprであるかどうかは関係ありません。関数自体にのみ適用され、戻り値には適用されません。戻り値にconstexprを指定するのは意味がありません。なぜなら、関数のためにすでにconstexprであるかどうかです。

だから、あなたのコードは、これらのポインタのいずれもconst charを指していないので、あなたが警告を得るでしょう

char* return_value = "XXX"; 
char* const return_value = "XXX"; 

を書くのと同じです。

2

constexprとは関係ありません。

char *foo() { return "ABC"; } 

は同じ警告を与えます。 "ABC"は文字列リテラルで、タイプはconst char[4](4つの定数charの配列)です。他の配列と同様に、型のポインタchar const *(定数charへのポインタ)に簡単に崩壊します。文字列リテラル(のみ)の場合

char *に非推奨の変換(非constのcharへのポインタ)もあります - あなたの関数を使用しているもので、それはGCCが好きではないものです。

char const *foo() ... 

または(同等)

const char *foo() ... 
関連する問題