Я столкнулся с интересной проблемой, которую пытался решить часами, но после долгих исследований и множества неудачных попыток я обнаружил, что задаю этот вопрос.
Я хотел бы написать 3 перегруженных функции, каждая из которых принимает один из следующих типов: const char*
, const char(&)[N]
и string literal (e.g. "BOO")
. Я понимаю, что строковый литерал - это просто массив символов, но, пожалуйста, потерпите меня, пока я объясняю свой подход.
Две нижеприведенные функции могут различать первые два типа (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]
, что имеет смысл, поскольку строковый литерал является просто массивом символов.
Вот где я дохожу до сути проблемы. Я не смог написать функцию, которая могла бы различать массив символов и строковый литерал. Я подумал, что одна вещь может сработать, это написать версию, которая принимает ссылку на rvalue:
template<std::size_t N>
void processStr(const char (&&charArr)[N])
{
std::cout << "From function that takes a \"const char(&&)[N]\" = " << charArr << '\n';
}
Но оказывается, что строковые литералы являются lvalues. Я также играл с разными версиями, которые используют std::enable_if
и std::is_array
, но я все еще не получаю результат, который ищу.
Итак, я думаю, что мой вопрос заключается в следующем: возможно ли провести различие между массивами символов и строковыми литералами в современном C ++?