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

Specjalizowany szablon metody statycznej

Cloud VPS
0 głosów
271 wizyt
pytanie zadane 4 kwietnia 2017 w C i C++ przez Ehlert Ekspert (215,050 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 (215,050 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 (158,980 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ź 381 wizyt
pytanie zadane 12 kwietnia 2018 w PHP przez niezalogowany
–1 głos
1 odpowiedź 490 wizyt
0 głosów
1 odpowiedź 977 wizyt

93,487 zapytań

142,423 odpowiedzi

322,773 komentarzy

62,909 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

Kursy INF.02 i INF.03
...