为什么我必须使用const和constexpr作为静态类函数?

时间:2016-11-12 15:35:31

标签: c++ c++11 constexpr

我正在尝试了解我在测试更改时看到的内容。该平台是带有GCC 4.8的openSUSE 42,但它可能会影响其他人。测试代码和错误如下。

$ 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和   static几乎是正交的(除了与静态的交互   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) 

3 个答案:

答案 0 :(得分:8)

函数声明上的

setValueAtTime表示函数是var context = new AudioContext(); var gain = context.createGain(); gain.connect(context.destination); var osc = context.createOscillator(); osc.frequency.value = 300; osc.connect(gain); osc.start(context.currentTime + 1); gain.gain.value = 0; ,而不是它的返回类型。

所以你的问题实际上归结为以下语法错误:

constexpr

从C ++ 11开始,这种从constexprchar * foo = "bar"; 的转换是非法的,并且自C ++ 98以来已被弃用。

使指针变为const而不是指向const的指针进行了更深入的探讨here

因此,要返回字符串文字,您需要使用char const[]char*char const*与此问题无关。

答案 1 :(得分:3)

字符串文章"..."的类型为const char[],即const个字符的数组。如果需要,它可以衰减到const char*

您收到警告是因为您使用的是从const char*char* / char* const的已弃用转化。函数是constexpr并不重要,它只适用于函数本身,而不适用于返回值。在返回值上指定constexpr是没有意义的,因为它或者因为函数而已经是constexpr。

因此,您的代码等同于编写

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

因为这些指针都没有指向const char,所以会收到警告。

答案 2 :(得分:2)

constexpr与此无关。

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

会给出同样的警告。 "ABC"是一个字符串文字,类型为const char[4](四个常量字符的数组)。像任何其他数组一样,它很容易衰变为类型为char const *的指针(指向常量字符的指针)。

对于字符串文字(仅限),还有一个不推荐的转换为char *(指向非const char的指针) - 这就是你的函数正在使用的,这就是海湾合作委员会不喜欢。修复是:

char const *foo() ...

或(等效地)

const char *foo() ...