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

Specjalizowany szablon metody statycznej

VPS Starter Arubacloud
0 głosów
188 wizyt
pytanie zadane 4 kwietnia 2017 w C i C++ przez Ehlert Ekspert (212,630 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,630 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ź 280 wizyt
pytanie zadane 12 kwietnia 2018 w PHP przez niezalogowany
–1 głos
1 odpowiedź 341 wizyt
0 głosów
1 odpowiedź 573 wizyt

92,417 zapytań

141,222 odpowiedzi

318,984 komentarzy

61,831 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

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 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!

...