Здравствуйте, Кодт, Вы писали:
К>Не разглядел emplace_back и make_shared в исходном сообщении. Старею?
Да, они там действительно не написаны в явном виде.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
TB>Да фиг знает, чёто такое, но это не сработает
Конечно, такое не сработает, потому что тут получается вывод типов сразу с двух сторон:
— из фактического типа аргумента
— из требований к аргументу, взятых из базы
А это запрещено стандартом.
Если отвлечься от конструктора, то решение именно так и выглядит
bar(X&);
bar(const Y&);
bar(volatile Z&);
template<class T> auto foo( T with cv-qualifiers etc & t ) -> sfinae if fits to bar(t) then void
{ bar(t); }
template<class T> auto foo( T with another cv-qualifiers etc & t ) -> sfinae if fits to bar(t) then void
{ bar(t); }
Конечно, если foo имеет много аргументов, это будет комбинаторный взрыв.
Но можно прибегнуть к частичному применению — т.е. заменить foo(T&&,U&&,V&&) на foo.start(T&&).and(U&&).and(V&&).go().
Каждая промежуточная функция унарная, сможет разобраться с двумя (или четыремя, если ещё volatile) вариантами и заначить правильную ссылку с правильным типом.
А превратить кортеж в серию вызовов — это boost preprocessor. Там даже основной тип для вариадиков — это именно sequence, (t)(u)(v).
Будет FOO(t,u,v,etc...) превращаться в foo(t)(u)(v)(etc...).go()
Ну или выбросить старый компилятор... Но это, как я понимаю, не вариант.