template do for_each

template do for_each
RE
  • Rejestracja:ponad 2 lata
  • Ostatnio:ponad 2 lata
  • Postów:41
0

tworząc template, chciałbym uniknąć pisania w pętli "for_each" print<int> lub print<string> wolałbym żeby tam stało samo słowo print

Kopiuj
// (Debian 10.2.1-6) Code::Blocks 20.03 -std=c++17 or higher
// g++ -Wall -fexceptions -g -std=c++17 -c main.cpp -o main.o

#include <iostream>
#include <algorithm> // for_each

using namespace std;

template<typename T>
void print(T const& x) {
    cout<<x<<' ';
}

int main()
{
    int tab[] = {21, 20, 33, 43, 15, 36, 777, 18, 9, 210};
    for_each(begin(tab),end(tab), [](const int &x){std::cout << x << " ";}  );
    cout<<'\n';
    for_each(rbegin(tab),rend(tab), print<int>);
    cout<<'\n';

    string SolarSystem[] = { "Sun", "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto" };
    for_each(begin(SolarSystem),end(SolarSystem), print<string>);
    cout<<'\n';

    std::for_each(begin(SolarSystem),end(SolarSystem), [](const auto& value) {
        print(value);
    });

    return 0;
}


RE
może inaczej, czy jest możliwość osiągnięcia takiego czegoś przy pomocy 1-go template
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:mniej niż minuta
4

Problemem jest moment w którym następuje dopasowanie szablonu.
W twojej wersji używasz funkcji for_each i dla argument print nie ma mechanizmu, który pozwałaby na detekcję typu tego szablonu.
Dla szablony funkcji detekcja typu funkcji następuje przy próbie wywołąnia funkcji i podania argumentów (tu nie podajesz arguemtów print).

Ergo można zrobić tak:

Kopiuj
struct print {
    template <typename T>
    void operator()(T const& x)
    {
        cout << x << ' ';
    }
};

int main()
{
    int tab[] = { 21, 20, 33, 43, 15, 36, 777, 18, 9, 210 };
    for_each(begin(tab), end(tab), [](const int& x) { std::cout << x << " "; });
    cout << '\n';
    for_each(rbegin(tab), rend(tab), print{});
    cout << '\n';

    string SolarSystem[] = { "Sun", "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto" };
    for_each(begin(SolarSystem), end(SolarSystem), print{});
    cout << '\n';

    std::for_each(begin(SolarSystem), end(SolarSystem), [](const auto& value) {
        print{}(value);
    });

    return 0;
}

https://godbolt.org/z/vdsx8E1of

Ale estetyka tego jest koślawa.

Można próbować to poprawić tak:
https://godbolt.org/z/dW8eYzxf6
ale to mi się jeszcze bardziej nie podoba.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22
Zobacz pozostałe 3 komentarze
WY
Wypierdzistyy
Ja do tego postu myślałem, że kompilatory tylko akceptują przeciązanie operatorów w classach niby to to samo, ale struktury z C się kojarzą, nie wiedziałem, że struktury też tak w C++ można jak klasy traktować, zaskoczyło mnie to.
WY
Wypierdzistyy
Nie no trochę znam C++ i bardzo dobrze C, ale po prostu zostawiłem te języki i jak się zastanowiłem to nie znałem tego, wewnętrznie myślałem, że kompilatory struktury traktują zwyczajnie jako jakieś bajty, a tu widzę, że można czasem coś ciekawego wykręcić.
MarekR22
Żeby było jasne, nie można stosować class i struct wymiennie. Jeśli jakiś symbol został zdefiniowany jak class to ma być zawsze używany jako class i odwrotnie. Kiedyś miałem taki błąd w kodzie i wyszło jako dziwny błąd linkowania (brak definicji funkcji mimo, że była).
SE
Z tego co sie orientuje, roznica miedzy class i struct jest po prostu taka, ze w klasie pola sa domyslnie private, a w structach public. Chodzi mi oczywiscie o to, ze sa funkcjonalnie rownowazne
MA
  • Rejestracja:około 5 lat
  • Ostatnio:prawie 2 lata
  • Postów:134
3

W tym konkretnym przypadku możesz użyć też lambdy + auto.

Kopiuj
auto print = [](auto const& x){cout<<x<<' ';};
RE
Dziękuję.
BG
  • Rejestracja:prawie 6 lat
  • Ostatnio:około 2 godziny
  • Postów:289
2

https://godbolt.org/z/77q36sfan

Kopiuj
#include <string>
#include <ranges>
#include <fmt/ranges.h>

int main()
{
    int tab[] = {21, 20, 33, 43, 15, 36, 777, 18, 9, 210};
    std::string SolarSystem[] = { "Sun", "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto" };

    fmt::print("{}\n", tab);
    fmt::print("{}\n", fmt::join(tab, " "));
    fmt::print("{}\n", SolarSystem);

    fmt::print("{}\n", tab | std::views::reverse );
    fmt::print("{}\n", fmt::join(SolarSystem | std::views::reverse, " --> "));
    return 0;
}
RE
biblioteki {fmt} do formatowania jeszcze nie znam, muszę się jej bliżej przyjrzeć. Dziękuję. p.s. formatowanie jak w python'ie
MarekR22
fmt jest super. Znaczna jej cześć wylądowała jako cześć standardu C++20. Niestety na razie tylko MSVC implementuje ten feature C++20.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.