【问题标题】:g++ treats returned string literal as const char pointer not const char arrayg++ 将返回的字符串文字视为 const char 指针而不是 const char 数组
【发布时间】:2014-02-26 22:03:03
【问题描述】:

从应该使用 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++ 规范的一个奇怪的角落 - 有人可以确认吗?

【问题讨论】:

  • 你在编译c++11,不是吗?
  • @Paranaix 我在 C++11 模式下的 GCC 4.8 上看到这个失败,所以即使 OP 不是,这也不是问题。
  • 字符串字面量在这里并不特殊,除了可能不推荐使用到 char* 的转换之外,它与其他数组的行为方式相同:const char foo[4] = {}; return foo; 失败并显示“错误:无法转换'( const char*)(& foo)' 从 'const char*' 到 'Test'"
  • 这同样适用于函数引用:它们被转换为指针,并且任何接受引用的构造函数都不可用:struct S { S(S(&amp;)()); }; S f() { return f; } 被 clang 接受,但 gcc 报告“错误:无法转换” f' 从 'S (*)()' 到 'S'" 解决方法可以是 return S(f);,或者在您的示例中为 return Test("foo");
  • @gwiazdorrr 你的意思是“如果”,而不是“因为”,确定吗?

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


【解决方案1】:

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

【讨论】:

【解决方案2】:

如果您想要一个可重用的 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 更改为不那么冗长的内容。

【讨论】:

    猜你喜欢
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多