我遇到了一个有趣的挑战,我已经尝试解决了几个小时,但是经过大量研究和许多失败的尝试,我发现自己在问这个问题。
我想编写3个重载函数,每个重载函数均采用以下类型之一:const char*
,const char(&)[N]
和string literal (e.g. "BOO")
。我知道字符串文字只是一个char数组,但是在解释我的方法时请耐心等待。
由于包装器类const char*
,下面的两个函数能够区分前两种类型(const char(&)[N]
和CharPtrWrapper
):
#include <iostream>
class CharPtrWrapper
{
public:
CharPtrWrapper(const char* charPtr)
: m_charPtr(charPtr)
{
}
const char * m_charPtr;
};
void processStr(CharPtrWrapper charPtrWrapper)
{
std::cout << "From function that takes a CharPtrWrapper = " << charPtrWrapper.m_charPtr << '\n';
}
template<std::size_t N>
void processStr(const char (&charArr)[N])
{
std::cout << "From function that takes a \"const char(&)[N]\" = " << charArr << '\n';
}
int main()
{
const char* charPtr = "ABC";
processStr(charPtr);
const char charArr[] = {'X', 'Y', 'Z', '\0'};
processStr(charArr);
}
输出:
From function that takes a CharPtrWrapper = ABC
From function that takes a "const char(&)[N]" = XYZ
现在,如果我使用字符串文字(例如processStr
)调用processStr("BOO")
,则将调用采用const char(&)[N]
的版本,这很有意义,因为字符串文字只是一个字符数组。
这是我解决问题的关键所在。我无法编写一个能够区分char数组和字符串文字的函数。我认为可能有用的一件事是编写一个带有右值引用的版本:
template<std::size_t N>
void processStr(const char (&&charArr)[N])
{
std::cout << "From function that takes a \"const char(&&)[N]\" = " << charArr << '\n';
}
但是事实证明,字符串文字是左值。我还玩过使用std::enable_if
和std::is_array
的不同版本,但仍然没有得到想要的结果。
所以我想我的问题是:在现代C ++中可以区分char数组和字符串文字吗?
答案 0 :(得分:2)
[...]表达式的类型是标识符的类型。的 结果是由 identifier 表示的实体。表达式是 如果实体是一个函数,变量或数据成员,并且一个 prvalue否则;如果标识符指定一个位,则为位字段 位字段([dcl.struct.bind])。
因此,给出了声明
const char arr[] = "foo";
表达式arr
是类型const char[4]
的左值。
还引用了普通字符串文字和UTF-8字符串文字 作为狭窄的字符串文字。窄字符串文字的类型为“数组 的 n
const char
”,其中 n 是定义的字符串大小 下方,并且具有静态存储期限。
并且根据[expr.prim.literal]:
litera 是主要表达。其类型取决于其形式。一种 字符串文字是左值;所有其他文字都是prvalue。
因此,表达式"foo"
是类型const char[4]
的左值。
结论:函数无法区分(const)char数组和字符串文字。