Может ли кто-нибудь сказать мне, как удалить повторяющиеся специализации ниже?Специализации для разных типов
#include <iostream>
#include <fstream>
#include <string>
struct Thing {
int a, b;
void load (std::istream& is) {is >> std::skipws >> a >> b;}
};
struct Object {
int a, b, c;
void load (std::istream& is) {is >> std::skipws >> a >> b >> c;}
};
template <typename...> struct PassArgs;
// General case.
template <typename First, typename... Rest>
struct PassArgs<First, Rest...> : PassArgs<Rest...> {
void operator()(std::istream& is, First& first, Rest&... rest) const {
is >> first;
PassArgs<Rest...>::operator()(is, rest...);
}
};
// Specialization for std::string needed.
template <typename... Rest>
struct PassArgs<std::string, Rest...> : PassArgs<Rest...> {
void operator()(std::istream& is, std::string& first, Rest&... rest) const {
while (std::getline (is, first) && first.empty());
PassArgs<Rest...>::operator()(is, rest...);
}
};
// Specialization for class Thing.
template <typename... Rest>
struct PassArgs<Thing, Rest...> : PassArgs<Rest...> {
void operator()(std::istream& is, Thing& first, Rest&... rest) const {
first.load(is);
PassArgs<Rest...>::operator()(is, rest...);
}
};
// Specialization for class Object, but is the exact same as that for Thing.
template <typename... Rest>
struct PassArgs<Object, Rest...> : PassArgs<Rest...> {
void operator()(std::istream& is, Object& first, Rest&... rest) const {
first.load(is);
PassArgs<Rest...>::operator()(is, rest...);
}
};
template <>
struct PassArgs<> {
void operator()(std::istream&) const {} // End of recursion.
};
int main() {}
Все работает правильно, но есть способ избежать специализаций для всех классов, которые имеют функцию load(std::istream&)
(и есть много в моей программе). В настоящее время у меня есть специализации для Thing
, Object
и многих других классов, которые имеют одинаковые строки в своих специализациях.
Кстати, это, как клиент использует PassArgs
:
template <typename T, typename... Args>
T* create (std::istream& is, Args&... args) {
PassArgs<Args...>()(is, args...);
T* t = new T(args...);
// Do whatever with t;
return t;
}
Если вы используете функцию загрузки вместо типа загрузки, вы можете получить настройку ADL в качестве бонуса. – Yakk
@Yakk, да, хотя это не всегда желательно –
Я думаю, что здесь есть что-то не так с классом 'void_t'. Я попытался полностью протестировать вашу реализацию: http://ideone.com/pxYwUF Заменить мои оригинальные 'ForwardArgs() (is, args ...);' с 'PassArgs () (is, args ...); 'в функции' T * create (std :: istream & is, Args & ... args) 'в моей тестовой программе, и она не компилируется. –
prestokeys