Существует список оберток Sqlite для.Net в http://www.sqlite.org/cvstrac/wiki?p=SqliteWrappers . Из того, что я услышал , http://sqlite.phxsoftware.com/ довольно хорош. Этот конкретный позволяет Вам доступ Sqlite через ADO.NET точно так же, как любая другая база данных.
If you're just concerned about readability you could do something like this:
typedef map<Vertex, Edge> AdjacencyList;
struct adjacency
{
adjacency(AdjacencyList::iterator& it)
: vertex(it->first), edge(it->second) {}
Vertex& vertex;
Edge& edge;
};
And then:
Vertex v = adjacency(it).vertex;
Вы не можете переименовать элементы, но у вас могут быть некоторые функции, которые могут помочь.
inline Vertex& vertex(map<Vertex, Edge>::iterator& it) {return it->first;}
inline Edge& edge(map<Vertex, Edge>::iterator& it) {return it->second;}
Тогда вместо it-> vertex
, как вы хотите, вы можете do vertex (it)
К сожалению, нет. Обычно я делаю следующее:
typedef map<Vertex, Edge> AdjacencyList;
typedef AdjacencyList::value_type Vertex_Edge_Pair;
Для удобства чтения. Внутри цикла вы также можете сказать
Vertex& current_vertex = it->first;
Edge& current_edge = it->second;
I liked KeithB's solution with free functions. However, a more reusable solution might be nice.
What about function objects that access first or second, as you can name the instances anything you like:
#include <map>
#include <string>
#include <iostream>
struct GetFirst
{
template <class First, class Second>
First& operator()(std::pair<First, Second>& p)
{
return p.first;
}
template <class First, class Second>
const First& operator()(const std::pair<First, Second>& p)
{
return p.first;
}
};
struct GetSecond
{
template <class First, class Second>
Second& operator()(std::pair<First, Second>& p)
{
return p.second;
}
template <class First, class Second>
const Second& operator()(const std::pair<First, Second>& p)
{
return p.second;
}
};
int main()
{
typedef std::map<std::string, int> Map;
Map persons;
persons["John"] = 20;
persons["Mary"] = 24;
//create named accessors
GetFirst name;
GetSecond age;
for (Map::iterator it = persons.begin(); it != persons.end(); ++it) {
std::cout << name(*it) << " is aging.\n";
++age(*it);
}
for (Map::const_iterator it = persons.begin(); it != persons.end(); ++it) {
std::cout << "Name: " << name(*it) << ", age: " << age(*it) << '\n';
}
}
This is the best I could do. I also tried to make those functors accept the iterator directly, but one way or another this means that the signature will contain dependent names which apparently makes template type deduction impossible (I couldn't find a way to overload GetSecond for iterator/const_iterator
even with deferred return type of C++0x).
Я бы не рекомендовал использовать это, но, похоже, работать, по крайней мере, до минимальной степени выполнения тестовой программы того, что я хотел / ожидал:
#include <map>
#include <string>
#include <iostream>
template <class T, class U>
struct my_pair : public std::pair<T, U> {
T const &vertex;
my_pair(std::pair<T, U> const &x) : std::pair<T, U>(x), vertex(x.first) { }
};
template <class T, class U>
struct my_map : public std::map<T, U> {
my_pair<T, U> find(T const &t) { return my_pair<T, U>(*std::map<T,U>::find(t)); }
};
class Vertex {
int x;
public:
Vertex(int v) : x(v) {}
bool operator<(Vertex const &other) const { return x < other.x; }
friend std::ostream &operator<<(std::ostream &os, Vertex const &v) { return os << v.x; }
};
int main() {
my_map<Vertex, std::string> m;
m[1] = "This is it";
my_pair<Vertex, std::string> mp = m.find(1);
std::cout << mp.vertex << ": " << mp.second;
return 0;
}
Sure, reimplement or wrap iterator, but is it worth the effort? Wouldn't
Vertex& v = it->first;
be easier?