Szablon klasy, problem z typem danych

0

Witam! Pracując nad szablonem klasy natrafiłem na następujący problem. Składową klasy jest vector, który w zależności od zadanego typu przy wywołaniu konstruktora (int,double,char,string itd) przyjmuje dane pochodzące od różnych metod składowych(tzn. np dla int przyjmuje liczby losowe a dla string ciągi wyrazów). Szablon posiada metodę add, która to rozpoznaje typ jaki zadaliśmy i na jego podstawie wywołuje odpowiednie funkcje( to co opisałem powyżej). W tym miejscu zaczyna się problem. Dla pojedynczego kodu ( zadeklarowane jedynie instrukcje dla int ) wszystko działa poprawnie lecz gdy tylko dodam metody zarówno dla int jak i dla string kompilator wykrywa problem z konwersją typów przy dodawaniu danych do wektora ( void std::vector<T,allocator<T>>:: push_back(_Ty&&)": nie można dokonać konwersji arguentu 1 z "int" do "const _Ty &")

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

using std::string;
using std::vector;
using std::clog;

template<typename T>
class X
{
        private:
	vector<T> vec;
        public:
	void add()
{
    if (typeid(F).name() == typeid(string).name())
	{
                     vec.reserve(10);
                     for(T &x  : vec)
                            x ="programista";
	}
	if (typeid(F).name() == typeid(int).name())
	{
                    vec.reserve(10);
                     for(T &x  : vec)
                            x =111;
	}
}
};

Podejrzewam co jest przyczyną tego problemu lecz nie mam pojęcia jak go rozwiązać. Czy wie ktoś może jak rozwiązać ten problem ? Dziękuję za odpowiedzi i pozdrawiam !

0

W danym kontekście to już jest konkretnie vector<int> lub vector<string> (lub inny). Równoważne więc jest to np. int i = "dupa". Nidyrydy w ten sposób.
Co próbujesz osiągnąć?

Tutaj jakaś alternatywa, chociaż poważnie zastanowiłbym się najpierw czy to na pewno dobry sposób na rozwiązanie twojego problemu.

#include <vector>
#include <string>
#include <iostream>
using namespace std;


template<typename T>
struct foo {
	vector<T> bar;
};

template<typename T>
void set(foo<T> &foo) {
	for (auto &el: foo.bar) {
		el = {};
	}
}

template<>
void set<int>(foo<int> &foo) {
	for (auto &el: foo.bar) {
		el = 111;
	}
}

template<>
void set<string>(foo<string> &foo) {
	for (auto &el: foo.bar) {
		el = "dupa";
	}
}

template<typename T>
void print(foo<T> const &foo) {
	for (auto const &el : foo.bar) {
		cout << el << " ";
	}
	cout << endl;
}

int main() {
	foo<int> f1 = { {1, 2, 3} };
	foo<double> f2 = { {1.0, 2.0, 3.0} };
	foo<string> f3 = { {"ala", "ma", "kota"} };
	
	set(f1);
	print(f1);
	
	set(f2);
	print(f2);
	
	set(f3);
	print(f3);
}

https://ideone.com/T9Hajd

5

Obawiam się, że to trochę problem XY. Sprawę da się załatwić za pomocą overloadingu, specjalizacji szablonów, tag dispatchingu, albo nawet - zachowując strukturę przykładowego kodu w 100% - constexpr if. Ale powiedz lepiej co chcesz osiągnąć.

1

Raz, @kq dobrze gada (polać mu! ;) ), napisz co dokładnie chcesz osiągnąć.
Dwa: te ify u Ciebie w kodzie aż się proszą o zostanie constexpr if albo specjalizację szablonu (osobiście wolę to drugie). Na oko - może CRTP by się nadał, ale głowy za to nie dam.
Natomiast, jeżeli to ma być runtime’owa rzecz, użyj np. std::variant i std::visit. Albo po prostu dziedziczenia, albo czegokolwiek innego, a templatkę wyrzuć.
Trzy, źle używasz reserve.

2

Problem bierze się stąd, że jest funkcja add() która sugeruje, że coś będzie dodawane, ale nie ma żadnych parametrów, więc nie wiadomo co i skąd będzie dodawać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1