Arhn - архитектура программирования

Перегрузка функций для const char*, const char(&)[N] и std::string

Чего я хочу добиться, так это иметь перегрузки функции, которые работают для строковых литералов и std::string, но вызывают ошибку времени компиляции для параметров const char*. Следующий код делает почти то, что я хочу:

#include <iostream>
#include <string>

void foo(const char *& str) = delete;

void foo(const std::string& str) {
    std::cout << "In overload for const std::string&     : " << str << std::endl;
}

template<size_t N>
void foo(const char (& str)[N]) {
    std::cout << "In overload for array with " << N << " elements : " << str << std::endl;
}   

int main() {
    const char* ptr = "ptr to const";
    const char* const c_ptr = "const ptr to const";
    const char arr[] = "const array";
    std::string cppStr = "cpp string";

    foo("String literal");
    //foo(ptr); //<- compile time error
    foo(c_ptr); //<- this should produce an error
    foo(arr);   //<- this ideally should also produce an error
    foo(cppStr);
}

Я недоволен тем, что он компилируется для переменной массива символов, но я думаю, что нет никакого способа обойти это, если я хочу принимать строковые литералы (если есть, скажите мне)

Однако я хотел бы избежать того, что перегрузка std::string принимает const char * const переменных. К сожалению, я не могу просто объявить удаленную перегрузку, которая принимает параметр const char * const&, потому что это также соответствовало бы строковому литералу.

Любая идея, как я могу заставить foo(c_ptr) выдавать ошибку времени компиляции, не затрагивая другие перегрузки?

05.01.2016

  • Между типом массива char и строковым литералом нет разницы, поэтому вы не можете исключить одно без другого. Но я думаю, что ваше другое требование выполнимо. 06.01.2016
  • @Tavian Barns: мне было интересно, можно ли использовать тот факт, что строковый литерал также является постоянным выражением (конечно, вы также можете создать массив constexpr) 06.01.2016

Ответы:


1

Этот код делает то, что нужно (кроме массива — литералы — это массивы, поэтому их нельзя разделить)

#include <cstddef>
#include <string>

template <class T>
void foo(const T* const & str) = delete;

void foo(const std::string& str);

template<std::size_t N>
void foo(const char (& str)[N]);

int main() {
    const char* ptr = "ptr to const";
    const char* const c_ptr = "const ptr to const";
    const char arr[] = "const array";
    std::string cppStr = "cpp string";

    foo("String literal");
    //foo(ptr); //<- compile time error
    // foo(c_ptr); //<- this should produce an error
    foo(arr);   //<- this ideally should also produce an error
    foo(cppStr);
}
05.01.2016
  • Спасибо. Я считаю, что с этой шаблонной функцией первая перегрузка (для const char *& str) больше не нужна, верно? 06.01.2016

  • 2

    Чтобы ваша удаленная функция не соответствовала лучше функции шаблона, чтобы строковые литералы продолжали работать, удаленная функция также должна быть шаблоном. Кажется, это удовлетворяет вашим требованиям (хотя массив все еще разрешен):

    template <typename T>
    typename std::enable_if<std::is_same<std::decay_t<T>, const char*>::value>::type
    foo(T&& str) = delete;
    

    Демо.

    05.01.2016
  • ... и я так и собирался это сделать, но ты меня опередил :) 06.01.2016
  • SFINAE здесь не требуется. 06.01.2016
  • Спасибо, я всегда об этом забываю 06.01.2016

  • 3

    В современных версиях языка вы можете создать некоторый пользовательский тип и пользовательский литерал, который его создаст, чтобы можно было передать "this"_SOMEWORDS, а не только строковый литерал c, указатель чата или массив символов.

    Это не совсем удовлетворяет вашим требованиям для передачи строкового литерала, но я думаю, что этого достаточно, особенно потому, что он запрещает также массивы

    05.01.2016
  • На самом деле это очень интересная идея, так как она позволяет различать массив символов и строковый литерал. Но это не мешает перегрузке std::string принимать параметр const char * const. 06.01.2016
  • @MikeMB Простое удаление (перегрузка const char*) теперь будет работать 06.01.2016
  • правильно - извините, уже поздно. Можно ли таким образом получить длину строкового литерала во время компиляции (как в моем примере функции с параметром шаблона)? 06.01.2016
  • @MikeMB, к сожалению, мне пока не удалось этого сделать. Кажется, что форма шаблона доступна только для целочисленных/плавающих литералов 06.01.2016
  • Нет проблем, это не является жестким требованием. Еще раз спасибо. До сих пор я использовал пользовательские литералы только в нескольких игрушечных примерах и просто не думал в этом направлении для решения проблемы. 06.01.2016
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..