Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Автоопределение типа в аргументе


Автор: SolRus 28.5.2012, 20:07
1. Хочу сделать также как find определяет тип, но так как непойму что ставить в аргументе,
Код
int listData::MyFunction(const T &p)  // T типа?

решил попробовать через шаблон
код на http://liveworkspace.org/code/9d40054a98a1b4a82bbd6f3ad65cccce или вот код:
Код
#include <iostream>
#include <algorithm>
#include <list>
#include <string>
using namespace std;
struct mData { 
   mData( int _a = 0, string _s = "") : a(_a), s(_s) {}
   bool operator == (const mData& m) { return (a == m.a) && (s == m.s); }
   bool operator == (const int &n) { return (a == n); }
   bool operator == (const string &n) { return (s == n); }
   int a;
   string s; 
};
struct listData : std::list<mData> {
   typedef std::list<mData> dt;
   template<typename T>  int MyFunction(const T &p);
};
template<typename T> int listData::MyFunction(const T &p) {
   listData::iterator nit = dt::begin(); int j = 0;
   nit = find(nit, dt::end(), p);
   if (nit != dt::end())
   if (nit->a == p) // вот здесь сбой, я незнаю как в шаблонах это раписать
   //if (typeid(int) == typeid(T)) ....
   //с typeid неполучилось пишет присвоение (а не ==) не найдено 
   //(string <-> int, но там должно быть только string-string, int-int)
   //.... код убераю чтоб не отвлекаться ....
      cout << "qwerty";
   return j;
}
int main () {
      listData f;
      f.push_back(mData(4, "as"));
      f.push_back(mData(9, "bs"));
      f.push_back(mData(3, "cs")); 
      f.push_back(mData(1, "ds")); 
      f.push_back(mData(42, "es")); 
          
      listData::iterator it = find(f.begin(),f.end(), 1);
      if (it != f.end()) cout << "find: " << it->s << endl;
      
      int j = f.MyFunction<int>(3); // Компилируется
      //int z = f.MyFunction<string>("5"); // так ошибка (nit->a)
      cout << j;
  return 0;
}
просто для примера, так не проходит
Код

bool a = true; int k = 0;
if (typeid(string) == typeid(T)) a = false;
if (!a)
    if (nit->s != p)  k=5;
else
    if (nit->a != p) k=10;

как сделать чтоб в зависимости от типа выбиралось (nit->a или nit->s)?

2. вообщем хотелось бы дописать const
Код
template<typename T> int listData::MyFunction(const T &p) const {
listData::iterator nit = dt::begin();    // тут ошибка
//....
}
т.е. как функция не меняющая вызывающего объекта, но показывает:
Цитата
error C2440: инициализация: невозможно преобразовать "std::_List_const_iterator<_Mylist>" в "std::_List_iterator<_Mylist>"
разве создание итератора изменяет объект? как это исправить?)

ps: но лучше бы вызывать без шаблона
Код
int j = list.MyFunction(5);    //на основе типа входящего аргумента и шло сравнение, как у find в STL

Автор: mes 28.5.2012, 20:38
Цитата(SolRus @  28.5.2012,  19:07 Найти цитируемый пост)
 Хочу сделать также как find определяет тип, но так как непойму что ставить в аргументе,

а по человечески можно сдормулировать задачу ?

Цитата(SolRus @  28.5.2012,  19:07 Найти цитируемый пост)
как сделать чтоб в зависимости от типа выбиралось (nit->a или nit->s)?

перегрузка функций ?



Цитата(SolRus @  28.5.2012,  19:07 Найти цитируемый пост)
разве создание итератора изменяет объект? как это исправить?)

const_iterator

Автор: boostcoder 28.5.2012, 20:55
Цитата(mes @  28.5.2012,  20:38 Найти цитируемый пост)
а по человечески можно сдормулировать задачу ?

поддерживаю.
но только не объясняйте что неполучается, а объясните чего хотите добиться.

Цитата(SolRus @  28.5.2012,  20:07 Найти цитируемый пост)
как сделать чтоб в зависимости от типа выбиралось (nit->a или nit->s)?

http://www.boost.org/doc/libs/1_49_0/libs/type_traits/index.html?

Автор: SolRus 28.5.2012, 20:57
Цитата(mes @ 28.5.2012,  20:38)
а по человечески можно сдормулировать задачу ?

ну смотри, когда find вызываешь то ему по барабану какой тип у третьего аргумента, ну и уменя взависимости от типа должен вызываться, ну как в полиморфизме, только не наследование, а тип
Цитата(mes @ 28.5.2012,  20:38)
перегрузка функций ?

ну делать перегрузку для каждого типа как то тупо, там всего то идет одно сравнение такого вида: nit->a / nit->s

c const_iterator не получается, сама переменная же не в объекте и насколько понимаю, должна изменятся не влияя на объект, значение итератора в объекте list не хранится же....

Цитата(boostcoder @ 28.5.2012,  20:55)
http://www.boost.org/doc/libs/1_49_0/libs/type_traits/index.html?

а без буста никак? пойду читать что оно такое... :(

Автор: boostcoder 28.5.2012, 21:09
Цитата(SolRus @  28.5.2012,  20:57 Найти цитируемый пост)
а без буста никак?

нужные тебе шаблоны закодить - пять минут работы. так что да, можно и без буста smile
а если твой компилятор умеет С++11 - то там все необходимые шаблоны есть.

вот только я все равно не понял задачу..

Добавлено через 44 секунды
ааа, понял smile
сейчас..

Автор: SolRus 28.5.2012, 21:29
Цитата(boostcoder @ 28.5.2012,  21:09)
вот только я все равно не понял задачу..
Добавлено @ 21:10
ааа, понял smile
сейчас..

надеюсь понял  smile 
вот там где сбой должно идти корректное сравнение, т.е. 
Цитата
входной string значит вызывается nit->s
входной int  вызывается nit->a
входной mData вызывается nit


ps: чето 5 минут растянулось  smile пойду поем пока...) "кто не... думает, тот ест" smile

Автор: boostcoder 28.5.2012, 21:33
если я все же правильно понял, то вотъ лекарство:
Код

#include <iostream>
#include <algorithm>
#include <list>
#include <string>
using namespace std;
struct mData { 
   mData( int _a = 0, string _s = "") : a(_a), s(_s) {}
   bool operator == (const mData& m) const { return (a == m.a) && (s == m.s); }
   bool operator == (const int &n) const { return (a == n); }
   bool operator == (const string &n) const { return (s == n); }
   int a;
   string s; 
};

///////////////////////////////
template<typename T>
struct selector;

template<>
struct selector<int> {
   static int func(const int& ) { return 0; }
};

template<>
struct selector<string> {
   static int func(const string& ) { return 1; }
};
///////////////////////////////

struct listData : std::list<mData> {
   template<typename T>
   int MyFunction(const T &p) const {
      const_iterator nit(find(begin(), end(), p));
      if ( nit != end() ) {
         selector<T>::func(p);
      }
      return 0;
   }
};

int main () {
      listData f;
      f.push_back(mData(4, "as"));
      f.push_back(mData(9, "bs"));
      f.push_back(mData(3, "cs")); 
      f.push_back(mData(1, "ds")); 
      f.push_back(mData(42, "es")); 
          
      listData::iterator it = find(f.begin(),f.end(), 1);
      if (it != f.end()) cout << "find: " << it->s << endl;
      
      int j = f.MyFunction(3); // Компилируется
      int z = f.MyFunction<string>("5"); // так ошибка (nit->a)
      cout << j << ":" << z << endl;
  return 0;
}

http://liveworkspace.org/code/886621e8694e2621c7125ae8a2ffe255

Добавлено через 2 минуты и 24 секунды
Цитата(SolRus @  28.5.2012,  21:29 Найти цитируемый пост)
чето 5 минут растянулось

пока писал, пришло в голову еще два понимания задачи. и того у меня их оказалось три. пришлось отсеивать два ненужных)

Добавлено через 11 минут и 51 секунду
Цитата(SolRus @  28.5.2012,  21:29 Найти цитируемый пост)
входной string значит вызывается nit->s
входной int  вызывается nit->a
входной mData вызывается nit

это уже сам впиши в selector<>::func()

Автор: SolRus 28.5.2012, 22:55
большое спасибо, boostcoder smile

на основе твоих специализаций шаблонов, сделал что нужно))

Код
struct listData : std::list<mData> {
   typedef std::list<mData> dt;
   template<typename T>  int MyFunction(const T &p);
private:
   template<typename T> struct selector;
   template<> struct selector<int>{ static int func(dt::const_iterator& k) { return k->a; } };
   template<> struct selector<string>{ static string func(dt::const_iterator& k) { return k->s; } };
};

вопрос решен!  smile 

Автор: boostcoder 28.5.2012, 22:58
Цитата(SolRus @  28.5.2012,  22:55 Найти цитируемый пост)
typedef std::list<mData> dt;

это тут зачем? smile 
*this у тебя и так наследует все публичные свойства/типы/методы предка.
разве мой пример без всей этой лабуды непонятней был?

Автор: SolRus 28.5.2012, 23:09
Цитата(boostcoder @ 28.5.2012,  22:58)
это тут зачем? smile 

точно, убрал  smile 
Цитата(boostcoder @ 28.5.2012,  22:58)
разве мой пример без всей этой лабуды непонятней был?

хы  smile ну разбирался минут 20-30 smile

Автор: boostcoder 28.5.2012, 23:19
Цитата(SolRus @  28.5.2012,  23:09 Найти цитируемый пост)
разбирался минут 20-30

я сказал с чем разбирался.
ну пусть будет так, раз тебе так удобней.

Автор: SolRus 28.5.2012, 23:32
Цитата(boostcoder @ 28.5.2012,  23:19)
я сказал с чем разбирался.
ну пусть будет так, раз тебе так удобней.

блин проглядел, что-то const ошибку дает:
Код
// внутри MyFunction
const_iterator nit, tit(begin());
nit(find(tit, end(), p));
if ((++nit) != end()) tit = nit;
было:
Код
iterator nit, tit = begin();
nit = find(tit, end(), p);
if ((++nit) != end()) tit = nit;


я так понимаю const_iterator не может изменятся? мне нужно чтоб изменялся итератор, значит функция не может быть const?

Автор: boostcoder 28.5.2012, 23:37
Цитата(SolRus @  28.5.2012,  23:32 Найти цитируемый пост)
значит функция не может быть const?

угу. иначе противоречие.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)