使用 constexpr、SFINAE and/or type_traits 对 char*、char 数组和字符串文字的重载解析
Overload resolution for char*, char array, and string literals using constexpr, SFINAE and/or type_traits
我 运行 遇到了一个有趣的挑战,我已经尝试解决了几个小时,但经过大量研究和多次失败的尝试后,我发现自己在问这个问题。
我想编写 3 个重载函数,每个函数采用以下类型之一:const char*
、const char(&)[N]
和 string literal (e.g. "BOO")
。我知道字符串文字只是一个字符数组,但在我解释我的方法时请耐心等待。
由于包装器 class CharPtrWrapper
:[=26=,下面的两个函数能够区分前两种类型(const char*
和 const char(&)[N]
) ]
#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', '[=12=]'};
processStr(charArr);
}
输出:
From function that takes a CharPtrWrapper = ABC
From function that takes a "const char(&)[N]" = XYZ
现在,如果我用字符串文字(例如 processStr("BOO")
)调用 processStr
,将调用采用 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++ 中是否可以区分字符数组和字符串文字?
[...] The type of the expression is the type of the identifier. The
result is the entity denoted by the identifier. The expression is an
lvalue if the entity is a function, variable, or data member and a
prvalue otherwise; it is a bit-field if the identifier designates a
bit-field ([dcl.struct.bind]).
因此,给定一个声明
const char arr[] = "foo";
表达式 arr
是类型 const char[4]
的左值。
根据 [lex.string]/8:
Ordinary string literals and UTF-8 string literals are also referred
to as narrow string literals. A narrow string literal has type “array
of n const char
”, where n is the size of the string as defined
below, and has static storage duration.
A litera is a primary expression. Its type depends on its form. A
string literal is an lvalue; all other literals are prvalues.
因此,表达式 "foo"
是类型 const char[4]
的左值。
结论:函数无法区分(const)字符数组和字符串文字。
我 运行 遇到了一个有趣的挑战,我已经尝试解决了几个小时,但经过大量研究和多次失败的尝试后,我发现自己在问这个问题。
我想编写 3 个重载函数,每个函数采用以下类型之一:const char*
、const char(&)[N]
和 string literal (e.g. "BOO")
。我知道字符串文字只是一个字符数组,但在我解释我的方法时请耐心等待。
由于包装器 class CharPtrWrapper
:[=26=,下面的两个函数能够区分前两种类型(const char*
和 const char(&)[N]
) ]
#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', '[=12=]'};
processStr(charArr);
}
输出:
From function that takes a CharPtrWrapper = ABC
From function that takes a "const char(&)[N]" = XYZ
现在,如果我用字符串文字(例如 processStr("BOO")
)调用 processStr
,将调用采用 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++ 中是否可以区分字符数组和字符串文字?
[...] The type of the expression is the type of the identifier. The result is the entity denoted by the identifier. The expression is an lvalue if the entity is a function, variable, or data member and a prvalue otherwise; it is a bit-field if the identifier designates a bit-field ([dcl.struct.bind]).
因此,给定一个声明
const char arr[] = "foo";
表达式 arr
是类型 const char[4]
的左值。
根据 [lex.string]/8:
Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n
const char
”, where n is the size of the string as defined below, and has static storage duration.
A litera is a primary expression. Its type depends on its form. A string literal is an lvalue; all other literals are prvalues.
因此,表达式 "foo"
是类型 const char[4]
的左值。
结论:函数无法区分(const)字符数组和字符串文字。