Если кто-то ищет Linq verson, это работает для меня:
public static IQueryable<BlockVersion> LatestVersionsPerBlock(this IQueryable<BlockVersion> blockVersions)
{
var max_version_per_id = blockVersions.GroupBy(v => v.BlockId)
.Select( v => new { BlockId = v.Key, MaxVersion = v.Max(x => x.Version) } );
return blockVersions.Where( v => max_version_per_id.Any(x => x.BlockId == v.BlockId && x.MaxVersion == v.Version) );
}
Ключевое слово this
используется с boost::bind
, когда объект функции, который вы создаете, привязан к функции объекта-объекта . Функции-члены не могут существовать отдельно от экземпляров, поэтому при создании объекта-функтора из функции-члена с boost::bind
вам нужен указатель на экземпляр. Именно это и есть ключевое слово this
. Если вы используете ключевое слово this
внутри функции-члена класса, то вы получаете указатель на текущий экземпляр этого класса.
Если вы должны были вызвать bind
из за пределами функция члена класса, вы можете сказать что-то вроде:
int main()
{
Foo f;
boost::thread* thr = new boost::thread(boost::bind(&Foo::some_function, &f));
}
Здесь мы используем Foo :: some_function как нашу функцию потока. Но мы не можем использовать this
, потому что мы вызываем bind
из main
. Но то же самое можно было бы сделать с помощью this
, если мы назовем bind
изнутри функции-члена Foo, например:
void Foo::func1()
{
boost::thread* thr = new boost::thread(boost::bind(&Foo::some_function, this));
}
Если функция-член статична или просто является регулярной (не-член), тогда вам вообще не нужен указатель на экземпляр. Вы просто сделали бы:
boost::thread* thr = new boost::thread(some_regular_function);
Если ваш объект является функтором, то есть имеет operator()
, вы можете передать его экземпляр в boost::thread
. operator()
не обязательно быть статичным. Например:
#include <boost/thread.hpp>
struct th {
void operator()();
};
void th::operator()()
{
for (;;) {
// stuff
}
}
int main()
{
th t;
boost::thread my_thread( t ); // takes a copy of t !
my_thread.join(); // blocks
return 0;
}
В подобных случаях полезно использовать нестатические функции-члены как свободные функции, которые принимают this
в качестве первого параметра, например, в вашем случае void MainThreadFunc(Main* this)
.
boost::thread
принимает нулевой функтор, поэтому вам нужно передать ему нулевой функтор, который содержит ссылку на экземпляр GUIMain
и вызовы GUIMain->MainThreadFunc
, которые, как я объяснил выше, были бы чем-то как MainThreadFunc(GUIMain)
.
Boost (и теперь также C ++ с TR1) предоставляет помощники для создания таких функторов, а именно boost::bind
(или, альтернативно, boost::lambda::bind
). Выражение boost::bind(f, arg1, arg2, ...)
означает «вернуть нулевой функтор, который вызывает f(arg1, arg2, ...)
».
При этом вы можете использовать следующее выражение для создания потока:
GUIThread = new boost::thread(boost::bind(&Main::MainThreadFunc, GUIMain))
Как уже упоминалось, когда вы хотите вызвать метод объекта в новом потоке, вы должны указать адрес этого объекта. Но вам не нужно вызывать boost::bind
, вы можете использовать перегруженный конструктор boost::thread
следующим образом:
GUIThread = new boost::thread(&Main::MainThreadFunc, GUIMain);
Если метод находится в том же классе, вы используете this
, чтобы получить адрес текущего экземпляра, например:
t = new boost::thread(&myclass::compute, this);
Если у метода есть параметры, вы можете указать их после второго аргумента, например:
t = new boost::thread(&myclass::compute, this, p1, p2);
boost :: bind - ваш друг (иногда может быть грубый способ показать его)!
использовать GUIThread = new boost::thread(boost::bind(&Main::MainThreadFunc, GUIMain));
, а затем сделать ваш MainThreadFunc регулярным членом , Это означает, что вы можете использовать переменные экземпляра напрямую, как обычно.
Что-то вроде этого:
class GUIMain {
public:
GUIMain() : m_Member(42) {}
void MainThreadFunc() {
// use all members as you would normally do
std::cout << m_Member << std::endl;
}
private:
int m_Member;
};