LINUX.ORG.RU

C++: а можно ли как-либо лябду указать в параметре шаблонного класса? Да еще и typedef'ом сделать?

 , ,


0

3

Можно ли как-либо лямбда-функцию указать в параметр шаблонного класса? Поясню, что меня интересует именно в параметр шаблона, а не указать в шаблоне тип, а в параметр метода указывать саму функцию.

Я попробовал сделать, но компилятор ругается: ошибка: lambda-expression in template-argument

template <typename I, typename T, std::function<I(const T&)>* fn >
struct TTest {
    static I index(const T& s) { return fn(s); }
};

struct TTust {
    quint32 value = 5;
};

void test() {
    TTust ss;
    qDebug() << TTest<quint32,TTust,[](const TTust& s) { return s.value; }>::index(ss);
}

Попробуй конст &

anonymous
()

enable_if, is_same

anonymous
()
#include <type_traits>
template <typename I, typename T, typename F>
struct TTest 
{
	static I index(const T& s) 
	{ 
		assert(std::is_convertible<F, std::function<I(const T&)>>);
		return F(s); 
	}
};

Точно нужно всё это делать в рантайме? Код выглядит как кандидат на constexpr и static_assert.

jcd ★★★★★
()

std::function не является литеральным типом и не может быть аргументом шаблона. Лямбда тоже.

CatsCantFly
()
Последнее исправление: CatsCantFly (всего исправлений: 1)
Ответ на: комментарий от slovazap

Опиши задачу

У меня есть шаблонный класс рб-дерева. В отличие от стандартного Map, ключевое значение хранится в сохраняемом значении:

template <typename Key,typename Value,typename FnGetKey>
class MyMap { /* implementation */ };

struct SomeObject {
   int key_value;
   /* ... some content */

   // этот вызов используется как получение ключа в
   //  в дереве, поскольку в данном случае сам же SomeObject будет
   //  будет передан третьим параметром шаблона
   static int key(const SomeObject& s) { return s.key_value; }
};

typedef MyMap<int,SomeObject,SomeObject> MapOfSomeObject;
Таким образом структуры занимают меньше памяти, когда ключевое значение должно быть и в ключе, и в самой структуре - большие деревья, большой расход памяти.

Некоторые структуры одна и та же индексируются в разных деревьях по разным ключевым значениям - разные сортировки, и разные оптимизации.

Вот и хочется шлепать эту индексацию не перегружая код избыточными структурами-функторами которые возвращают ключевые значения. Т.е. указывать лямбду непосредственно в определении типа переменной дерева. Сохранять лямбду как значение в этом дереве это то же избыточное использование.

victor79
() автор топика
Ответ на: комментарий от victor79

В отличие от стандартного Map, ключевое значение хранится в сохраняемом значении

Ты описал std::set

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от victor79

Вот и хочется шлепать эту индексацию не перегружая код избыточными структурами-функторами которые возвращают ключевые значения ... Сохранять лямбду как значение в этом дереве это то же избыточное использование.

Можно использовать pointer to member на поле с ключём в параметре шаблона или просто указатель на статическую функцию, лямбда тут не нужна.

mashina ★★★★★
()

Даже STL с этим не заморачивается, передавай свой функтор просто как Functor f, да и всё.

yoghurt ★★★★★
()

Почему то никогда не понимаю сути вопросов на форуме ЛОРа, особенно в части Си++ :-)

anonymous
()

читай потом за ними код...

next_time ★★★★★
()
Ответ на: комментарий от victor79

Используй std::{unordered}_set, как уже сказали выше. У этих структур есть шаблонный параметр Compare или Hash + KeyEqal, который как раз то что тебе нужно. Если стандартный не устраивает - используй буст и остальные. Если и они не айс - пиши свой контейнер в том же стиле, что и STL/Boost.

Т.е. твое желание передать геттер в контейнер - плохо с точки зрения архитектуры, ведь алгоритмам внутри важно лишь отношение или хэш.

«Избыточный» код со структурами-функторами лучше написать. Т.е. можно конечно писать так:

std::set<Book, decltype([](Book const& a, Book const& b) { return a.title() < b.title(); })> s;

но тогда тип этой переменной в ошибках компилятора будет длинный и непонятный без подглядывания в код. С std::set<Book, CompareBooksByTitle> - сразу ясно о чем речь.

snizovtsev ★★★★★
()
Ответ на: комментарий от snizovtsev

«Избыточный» код со структурами-функторами лучше написать. Т.е. можно конечно писать так:

Чё?

anonymous
()
Ответ на: комментарий от snizovtsev

с пустым capture list будет не функтор и set его не сожрет.

Будет функтор, но оператор-скобки у него будет статичным, и вот этот оператор уже можно использовать как обычную функцию. Но в данном случае даже попытка выписать данную конструкцию будет слишком монструозна, куда прямее и проще добавить обычную функцию.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.