• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Specjalizowany szablon metody statycznej

Object Storage Arubacloud
0 głosów
194 wizyt
pytanie zadane 4 kwietnia 2017 w C i C++ przez Ehlert Ekspert (212,670 p.)

Cześć,

pytanie zadane z bezradności bo już nie wiem jak crying

Posiadam klasę w której chcę umieścić szablon na metodę statyczną i od razu ciała metod specjalizowanych dla konkretnych typów bo innych używać nie będę. Może mi ktoś podrzucić schematyczny przykład i powiedzieć... Da się to rozbić na pliki czy tylko i wyłącznie w jednym pliku?

komentarz 4 kwietnia 2017 przez Ehlert Ekspert (212,670 p.)
class Wrapper{
public:

template<class Type>
static Type* get<Type>(const std::string&) {
    std::cout << "Generyczna, typ ogólny!\n";
    return nullptr;
}

template<>
static int* get<int>(const std::string&) {
    std::cout << "Specjalizowana dla inta!\n";
    return new int(1);
}

};

1 odpowiedź

+2 głosów
odpowiedź 4 kwietnia 2017 przez mokrowski Mędrzec (155,460 p.)
wybrane 4 kwietnia 2017 przez Ehlert
 
Najlepsza

Wyrzucenie implementacji szablonów poza definicje klasy:

wrapper.hpp

#pragma once
#include <string>
#include <iostream>

class Wrapper{
public:
 
template<class Type>
static Type* get(const std::string&);

template<class Type>
Type member() const;
 
};

template<class Type>
Type* Wrapper::get(const std::string&) {
    std::cout << "Generyczna, typ ogólny!\n";
    return nullptr;
}

template<class Type>
Type Wrapper::member() const {
    return Type{};
}

template<>
int* Wrapper::get(const std::string&) {
    std::cout << "Specjalizowana dla inta!\n";
    return new int(1);
}

template<>
int Wrapper::member() const {
    return 42;
}

main.cpp

#include "wrapper.hpp"

int main() {
    Wrapper w1;
    auto p1 = Wrapper::get<double>("abrakadabra");
    auto p2 = Wrapper::get<int>("hokus pokus");
    std::cout << "get<int>() = " << *p2
        << "\nget<double>() = " << (p1 == nullptr ? "pusty" : "nie")
        << "\nmember<double>() = " << w1.member<double>() 
        << "\nmember<int>() = " << w1.member<int>()
        << std::endl;
}

Dodałem jeszcze jakiegoś membera w klasie dla wyczerpania przykładu.

1. Rozwiązanie pierwsze, stosuje np. Qt. Tam jest stosowane z powodu pracy moc'a (Meta Object Compiler). On parsuje pliki *.cpp i rozwija "magiczne makra" :-)

a) Wyrzucamy definicje do pliku wrapper.cpp

#include "wrapper.hpp"

template<class Type>
Type* Wrapper::get(const std::string&) {
    std::cout << "Generyczna, typ ogólny!\n";
    return nullptr;
}

template<class Type>
Type Wrapper::member() const {
    return Type{};
}

template<>
int* Wrapper::get(const std::string&) {
    std::cout << "Specjalizowana dla inta!\n";
    return new int(1);
}

template<>
int Wrapper::member() const {
    return 42;
}

b) Zmieniamy plik wrapper.hpp na:

#pragma once
#include <string>
#include <iostream>

class Wrapper{
public:
 
template<class Type>
static Type* get(const std::string&);

template<class Type>
Type member() const;
 
};

#include "wrapper.cpp" // Tak.. dobrze widzisz.. włączanie *.cpp :-)

Wygląda jak wygląda. Mnie się nie podoba... można lepiej :-)

2. Rozwiązanie z dodaniem instancjonowania szablonu.

Pełna zawartość plików:

main.cpp (nie zmienił się)

wrapper.hpp

#pragma once
#include <string>
#include <iostream>

class Wrapper{
public:
 
template<class Type>
static Type* get(const std::string&);

template<class Type>
Type member() const;
 
};

Teraz wrapper.hpp wygląda nieźle :-)

wrapper.cpp:

#include "wrapper.hpp"

template<class Type>
Type* Wrapper::get(const std::string&) {
    std::cout << "Generyczna, typ ogólny!\n";
    return nullptr;
}

template<class Type>
Type Wrapper::member() const {
    return Type{};
}

template<>
int* Wrapper::get(const std::string&) {
    std::cout << "Specjalizowana dla inta!\n";
    return new int(1);
}

template<>
int Wrapper::member() const {
    return 42;
}

// Tu jest wymuszenie instancjonowania szablonów.. 
template double* Wrapper::get<double>(const std::string&);
template double Wrapper::member<double>() const;

W ramach usprawnień, wyrzucam jeszcze te wymuszenia do pliku wrapper_impl.cpp i robię we wrapper.cpp na końcu pliku

#include "wrapper_impl.cpp"

Mam nadzieję że jasne :-)

Podobne pytania

0 głosów
1 odpowiedź 288 wizyt
pytanie zadane 12 kwietnia 2018 w PHP przez niezalogowany
–1 głos
1 odpowiedź 359 wizyt
0 głosów
1 odpowiedź 639 wizyt

92,572 zapytań

141,422 odpowiedzi

319,643 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...