2016-11-07 8 views
1

Так что я столкнулся с проблемой, когда у меня есть функция с несколькими параметрами. Из удобства я начал перегружать его так, что для instace я могу передать std::string вместо экземпляра std::fstream. В этой перегрузке из этой строки будет построен новый std::fsteam, а затем вызывается другая функция. Пример:Функция с несколькими типами для одного и того же параметра

void func(const std::string & filename) { 
    std::fstream file(filename); 

    func(file) 
} 

void func(std::fstream & file) { 
    // ... 
} 

Это все работает нормально. Но когда вы начинаете делать это для более чем одного параметра или более двух возможных типов, все начинает становиться беспорядком, и вам, возможно, придется написать много перегрузок с дублирующимся кодом и т. Д.
Так что мне было интересно, было ли более элегантное решение для эта проблема для столько параметров, сколько вам нужно.

Я знаю, что эта проблема не специфична для C++, но меня интересуют решения проблемы на C++.

+3

Вы слышали о шаблонах? – NathanOliver

+0

Да. Однако я не уверен, как я могу использовать их в этом конкретном случае. – BrainStone

+3

Вы можете специализировать шаблоны, и вы также можете указать условия для определенных типов с [характерными чертами] (http://en.cppreference.com/w/cpp/header/type_traits). – wally

ответ

1

Так что я нашел довольно приличный и расширяемую решение:

Давайте предположим, что у нас есть функция, которая принимает 3 paramters типа type_right1, type_right2 и type_right3, но мы также хотим, чтобы обеспечить его дополнительными перегрузками для соответствующего типы type_right1, type_wrong2 и type_wrong3. Мы также можем получить от type_wrongX до type_rightX, мы просто вызываем конструктор последнего и передаем первый. Код выглядит следующим образом:

template<class T1, class T2> 
void func(type_wrong1 arg1, T1 arg2, T2 arg3) { 
    func(type_right1(arg1), arg2, arg3); 
} 

template<class T1> 
void func(type_right1 arg1, type_wrong2 arg2, T1 arg3) { 
    func(arg1, type_right2(arg2), arg3); 
} 

void func(type_right1 arg1, type_right2 arg2, type_wrong3 arg3) { 
    func(arg1, arg2, type_right2(arg3)); 
} 

void func(type_right1 arg1, type_right2 arg2, type_right3 arg3) { 
    // actual function 
} 

Это решение может быть легко расширено с обеими более параметрами и более двух типов в параметр и требует намного меньше писать, а также просто генерирует функцию, которые вам действительно нужно!
Благодарим за помощь.

2

Одним из возможных решений является использование вспомогательных классов:

class param1 { 

public: 
    param1(const std::string & filename) 
      : filename(filename), file(nullptr) 
    { 
    } 

    param1(std::fstream &file) : file(&file) 
    { 
    } 

    std::string filename; 
    std::fstream *file; 
}; 

class param2 { 

public: 
    param2(int flag); 
    param2(some_particular_class &classptr); 

    // etc... 
}; 

void func(const param1 &p1, const param2 &p2); 

Вспомогательный класс для каждого параметра содержит перегруженные конструкторы для каждого возможного типа, которые могут быть переданы в итоге вы один func() реализовать..

В каждом классе-помощнике вам нужно выяснить, как правильно хранить каждый параметр, и это будет другой вопрос.

С C++ 14 вы также можете использовать std::variant здесь.

+0

Использование вспомогательных классов кажется немного чрезмерным. – BrainStone

+0

Не когда у вас есть четыре или пять параметров, и каждый параметр может быть любой доступной альтернативой. Возможные варианты: либо десятки, либо не сотни перегруженных функций; сгенерированный шаблоном код; или это. Выбери один. –

+0

В последнем случае я согласен. На самом деле это вопрос предпочтений и обстоятельств, которые я бы сказал. – BrainStone

 Смежные вопросы

  • Нет связанных вопросов^_^