Как иметь переменный параметр типа данных?

Как видите, я неправильно использую тип данных auto в функции log(). Но я думаю, что это демонстрирует то, что мне нужно. Я пытаюсь создать простую оболочку cout и не знаю, как она будет выглядеть для любого типа данных.

void log(auto str = "DEFAULT LOG", bool b_endl = true)
{
    std::cout << str; if (b_endl == true) { std::cout << std::endl; }
}

int main() 
{ 
    log("string");
    log(3);
    log(3.0);
    return 0;
}

Шаблоны (template <class TYPE> void log(TYPE str = "DEFAULT LOG", bool b_endl = true)) здесь ваши друзья, но учтите, что не все могут принимать строку в качестве аргумента по умолчанию и имеют перегрузку <<.

user4581301 09.08.2024 23:19

Если вы не склонны иметь аргумент по умолчанию на str, я могу написать ответ. Если вам НУЖЕН этот дефолт, вам придется подождать кого-то гораздо более хитрого, чем я. Это или смириться с перегрузкой.

user4581301 09.08.2024 23:26

«Но я думаю, что это демонстрирует то, что мне нужно». -- Вы можете так подумать, но лучше описать желаемую функциональность словами (с кодом в качестве запасного варианта).

JaMiT 09.08.2024 23:56

@JaMiT Это название;)

Code N00b 10.08.2024 00:03

@user4581301 user4581301 Спасибо, я поищу шаблоны, потому что даже не знаю, что это такое!

Code N00b 10.08.2024 00:04

Рад, что вы прокомментировали. Не осознавал, что каким-то образом превратил свой ответ в совершенно другой вопрос.

user4581301 10.08.2024 00:05

@user4581301 user4581301 Строка по умолчанию для str не нужна для моих нужд.

Code N00b 10.08.2024 00:05

@CodeN00b «Это название» — что конкретно означает «это» в этом контексте? Все, что я вижу в заголовке, — это краткое изложение вашей цели, а не функциональных требований. Хорошо иметь в заголовке просто краткое изложение (см. Как задать вопрос), но этого недостаточно для описания вашего функционала. Показательный пример: ваш заголовок не дает указания на то, почему первый параметр должен иметь значение по умолчанию. Детали имеют значение, а резюме по своей природе не содержат подробностей.

JaMiT 10.08.2024 00:06

Я не уверен, что вы ищете. Код, который вы опубликовали , компилируется и выдает именно тот результат, который я ожидал . Вы спрашиваете о вызове без аргументов?

Miles Budnek 10.08.2024 00:13

Разве не здорово, когда со временем компиляторы становятся все более способными? Майлз использует самую последнюю версию стандарта языка C++. И я подумал, что дерзко добавляю заметку о концепциях C++20.

user4581301 10.08.2024 00:16

@ user4581301 auto параметры работают и с C++20.

Miles Budnek 10.08.2024 00:25

@Майлз, сукин сын. Так и есть. Мне следовало прочитать аннотации более внимательно.

user4581301 10.08.2024 00:43

Чем больше текста описывается, что вы пытаетесь сделать, тем больше вероятность того, что ответы, которые вы получите, помогут кому-то еще в будущем. Меньше текста == меньше возможностей для поиска.

JaMiT 10.08.2024 01:33
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
13
73
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Примечание. Код Asker будет работать, начиная с C++20. Поскольку это не так, ответ написан, главным образом, при условии, что C++20 недоступен.

Используйте шаблон для разрешения типа аргумента. Вы теряете возможность вызова функции без параметров и только с аргументами по умолчанию, не можете вывести аргумент шаблона без аргумента, но это легко исправить с помощью перегрузки, если возможность вызова log() является жестким требованием.

#include <iostream>
#include <string>

template <class TYPE>
void log(TYPE str, bool b_endl = true)
{
    std::cout << str; 
    if (b_endl == true) 
    { 
        std::cout << std::endl; 
    }
}

//for the totally parameter-less version
void log()
{
    std::cout << "DEFAULT LOG" << std::endl;
}

int main() 
{ 
    log("string");
    log(3);
    log(3.0);
    log(); 
    return 0;
}

Пример вывода:

string
3
3
DEFAULT LOG

Примечание. Вы по-прежнему будете получать ошибки, если передадите аргумент, который невозможно разрешить (например: log({1,2,3,4});) или аргумент, который нельзя напечатать с помощью << (например: log(std::vector<int>());). Начиная с C++20, вы можете получить немного более понятную ошибку. сообщение, если аргумент шаблона не может быть передан в потоковом режиме с помощью concept:

#include <iostream>
#include <string>
#include <vector>

template<class TYPE>
concept outstreamable = requires(std::ostream & out, TYPE b) {
  out << b;
};

template <class TYPE> requires outstreamable<TYPE>
void log(TYPE str, bool b_endl = true)
{
    std::cout << str; 
    if (b_endl == true) 
    { 
        std::cout << std::endl; 
    }
}

//for the totally parameter-less version
void log()
{
    std::cout << "DEFAULT LOG" << std::endl;
}

int main() 
{ 
    log("string");
    log(3);
    log(3.0);
    log(std::vector<int>());
    return 0;
}

Эта версия позволяет вам узнать, что требование TYPE быть outstreamable было нарушено, вместо того, чтобы выплевывать страницу за страницей шаблоны, которые были опробованы, но не смогли соответствовать.

Спасибо за подробный пример!

Code N00b 10.08.2024 01:41

@CodeN00b Обратите внимание на точку зрения Майлза в комментариях к вопросу о том, что если вы обновите свой компилятор и создадите его на C++20 или выше, то, что вы пробовали, будет работать.

user4581301 10.08.2024 01:47

Небольшая придирка: log() вместо этого следует брать параметр TYPE по ссылке на константу: void log(const TYPE &str, ...) и то же самое с outstreamable

Remy Lebeau 10.08.2024 03:01
#include <iostream>

// General template to handle multiple arguments
template<typename... Args>
void log(Args... args) 
{
    (std::cout << ... << args) << std::endl;
}

// Specialization or overload for no arguments, providing a default log
void log() {
    std::cout << "DEFAULT LOG" << std::endl;
}

int main() 
{
    log("Logging: ", 1, " and ", 2.5); // Handles multiple types
    log("Another log with a single parameter");
    log(); // Uses the default log
    return 0;
}

Другие вопросы по теме