C++ — это язык статически типизированный. Это означает, что все типы должны быть определены при компиляции: вы не можете вводить новые типы при запуске программы.
- создание вектора типа void (очевидно, это не разрешено сейчас, когда я его изучил, упс)
void
на самом деле довольно странный тип, в основном заполнитель, когда вы ожидаете тип (например, тип возвращаемого значения функции) и не можете его предоставить. void*
используется в качестве указателя на неизвестный тип (в основном в C), но это настоящий хак, потому что информация об оригинале отбрасывается (насколько это касается языка), поэтому это вызывает проблемы с фактическими действиями со значением так получается.
перегружая функцию с именем insertInVector, отправляя первый элемент в функцию и позволяя функции определить, какой тип вектора создать на основе типа первого элемента
#include <typeinfo>
в программе, найти тип первого элемента, а затем создать вектор, используя vector<typeid(firstElement).name()>
, и, честно говоря, я не уверен, почему это не сработало, но это не сработало.
К сожалению, ни то, ни другое невозможно: поскольку вы не можете объявить переменную без типа, каким должен быть тип firstElement
для начала?
Проблема, которую вы описываете, вообще сложна. В основном это означает, что вам придется принять строку символов, а затем закодировать набор правил, чтобы определить, как интерпретировать эти символы. Обычно это делается с помощью грамматики для кодирования этих правил; но грамматика может быть сложной для того, что, вероятно, является простой задачей.
Позвольте мне собрать небольшой пример:
class Input {
public:
enum Type {
Int,
Double,
String
};
static Input Parse(std::string const& s);
Input(): _type(Int), _int(0), _double(0.0) {} // need to define a default...
Type type() const { return _type; }
int asInt() const {
assert(_type == Int && "not an int");
return _int;
}
double asDouble() const {
assert(_type == Double && "not a double");
return _double;
}
std::string const& asString() const {
assert(_type == String && "not a string");
return _string;
}
private:
Type _type;
int _int;
double _double;
std::string _string;
};
Очевидно, что настоящая проблема состоит в том, чтобы правильно Parse
ввести данные.
Идея состоит в том, чтобы использовать набор правил, например:
int
состоит исключительно из цифр, возможно с префиксом -
double
состоит исключительно из цифр, не более чем с одним .
и необязательно с префиксом -
string
может быть чем угодно, поэтому это наш универсальный
Затем мы можем написать часть распознавания метода Parse
:
static bool isInt(std::string const& s) {
if (s.empty()) { return false; }
// The first character may be among digits and '-'
char const first = s.at(0);
if (not isdigit(first) and first != '-') { return false; }
// Subsequent characters may only be digits
for (char c: s.substr(1)) {
if (not isdigit(c)) { return false; }
}
// Looks like it is an int :)
return true;
} // isInt
// Note: any int could be interpreted as a double too
static bool maybeDouble(std::string const& s) {
if (s.empty()) { return false; }
// The first character may be among digits, '.' and '-'
char const first = s.at(0);
if (not isdigit(first) and first != '.' and first != '-') { return false; }
// There may only be one dot
bool hasSeenDot = s.at(0) == '.';
// Subsequent characters may only be digits and a dot now
for (char c: s.substr(1)) {
if (not isdigit(c) and c != '.') { return false; }
if (c == '.') {
if (hasSeenDot) { return false; } // no second dot allowed
hasSeenDot = true;
}
}
// Looks like it could be a double
return true;
} // maybeDouble
static Input::Type guessType(std::string const& s) {
if (isInt(s)) { return Input::Int; }
// Test double after we ensured it was not an int
if (maybeDouble(s)) { return Input::Double; }
return Input::String;
} // guessType
И с логикой угадывания вместе, наконец, приходит синтаксический анализ:
Input Input::Parse(std::string const& s) {
Input result;
result._type = guessType(s);
switch(result._type) {
case Input::Int: {
std::istringstream stream(s);
s >> result._int;
return result;
}
case Input::Double: {
std::istringstream stream(s);
s >> result._double;
return result;
}
case Input::String:
result._string = s;
return result;
}
// Unreachable (normally)
abort();
} // Input::Parse
Фу!
Так ? Почти готово. Теперь нам нужно определить, как сравнивать два входа. Это легко, если все они имеют один и тот же тип, в противном случае вам нужно будет определить произвольную логику. Вы можете достаточно легко преобразовать ввод Int во вход Double, но для строки это немного более странно.
// define < for comparing two instance of "Input",
// assuming they both have the same type
bool operator<(Input const& left, Input const& right) {
assert(left.type() == right.type() && "Different Types!");
switch(left.type()) {
case Input::Int: return left.asInt() < right.asInt();
case Input::Double: return left.asDouble() < right.asDouble();
case Input::String: return left.asString() < right.asString();
}
} // operator<
И, наконец, программа:
int main(int argc, char* argv[]) {
// parse command line
std::vector<Input> inputs;
// by convention argv[0] is the program name, it does not count!
for (int i = 1; i != argc; ++i) {
inputs.push_back(Input::Parse(argv[i]));
// Detect that the type is the same as the first input
if (inputs.size() >= 2) {
if (inputs.back().type() != inputs.front().type()) {
std::cerr << "Please only use one type among Int, Double and String\n";
return 1; // non-0 is an error
}
}
}
// sort
std::sort(inputs.begin(), inputs.end());
// echo back to the user
for (Input const& i: inputs) {
switch(i.type()) {
case Input::Int: std::cout << i.asInt() << "\n"; break;
case Input::Double: std::cout << i.asDouble() << "\n"; break;
case Input::String: std::cout << i.asString() << "\n"; break;
}
}
// End of the program
return 0;
}
Конечно, поскольку я не знаю, с какими типами вы хотите иметь дело. Я выбрал произвольный набор ;) Однако это должно дать вам скелет, на котором можно основываться.
person
Matthieu M.
schedule
10.06.2012
boost::any
. Аргумент шаблона необходимо передать во время компиляции. - person chris   schedule 10.06.2012vector<void>
нельзя...vector<void*>
можно. И на самом деле все требования кажутся немного странными. Вы уверены, что это лучший подход? И это домашнее задание? - person Zaid Amir   schedule 10.06.2012Yes, this is homework.
Тогда вам следует добавить тег домашнего задания к вашему вопросу - person Zaid Amir   schedule 10.06.2012