g ++将返回的字符串文字视为const char指针而不是const char数组

时间:2014-02-26 22:03:03

标签: c++ g++ string-literals

我从一个应该用g ++(版本4.7.3)执行隐式转换的函数返回一个字符串文字时,会看到一些奇怪的行为。任何人都可以解释为什么以下代码:

#include <stdio.h>

class Test
{
public:
  template <unsigned int N>
  Test(const char (&foo)[N])
  {
    printf("Template const char array constructor\n");
  }

  Test(char* foo)
  {
    printf("char* constructor\n");
  }
};

Test fn()
{
  return "foo";
}

int main()
{
  Test t("bar");
  Test u = fn();

  return 0;
}

产生结果:

Template const char array constructor
char* constructor

关于g ++?令人惊讶的是,在从fn()生成返回值时,首先选择char *构造函数而不是const char数组构造函数。不可否认,有一个警告,“从字符串常量转换为'char *'”

更令人惊讶的是,如果删除char *构造函数,则代码不会使用g ++进行编译。

它与clang(两次使用模板构造函数)一样正常工作,这让我觉得这是一个编译器错误,但也许它只是C ++规范的一个奇怪的角落 - 任何人都可以确认吗?

2 个答案:

答案 0 :(得分:6)

这似乎是一个影响gcc的几个版本的错误,这个错误已经反复报道,最近一个月前反对最新版本4.8.2。见http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24666

答案 1 :(得分:1)

如果你想要一个可重用的C ++ 03解决方法(即你不必关心返回类型是什么,只要它可以从char数组构造),你将不得不使用某种形式一个char数组包装器。

template <size_t N>
struct char_array_ref
{
    typedef const char (&ref_type)[N];
    ref_type ref;

    template <typename T>
    operator T() const
    {
        return T(ref);
    }
};

template <size_t N>
char_array_ref<N> stupid_gxx_use_array_reference(const char (&chars)[N])
{
    return char_array_ref<N> { chars };
}


Test fn()
{
  return stupid_gxx_use_array_reference("foo");
}

也很容易将正则表达式传播到您的代码库中。

显然,在您的代码中,您可以将stupid_gxx_use_array_reference更改为更简洁的内容。