Сводка
Учитывая тип с конструктором конструкторов Variadic, который перенаправляет аргументы в класс реализации, можно ли ограничивать типы, пересылаемые с помощью SFINAE?
Подробнее
Сначала рассмотрим невариантный случай, когда конструктор принимает универсальную ссылку. Здесь можно отключить пересылку ссылки на константу без ссылки через SFINAE, чтобы вместо этого использовать конструктор копирования.
struct foo
{
foo() = default;
foo(foo const&)
{
std::cout << "copy" << std::endl;
}
template <
typename T,
typename Dummy = typename std::enable_if<
!std::is_same<
T,
typename std::add_lvalue_reference<foo>::type
>::value
>::type
>
foo(T&& x)
: impl(std::forward<T>(x))
{
std::cout << "uref" << std::endl;
}
foo_impl impl;
};
Это ограничение универсальной ссылки полезно, потому что в противном случае класс реализации получит неконстантный ссылочный номер типа foo
, о котором он не знает.
Полный пример в LWS.
Вопрос
Но как это работает с вариативными шаблонами? Это вообще возможно? Если да, то как? Наивное расширение не работает:
template <
typename... Args,
typename Dummy = typename std::enable_if<
!std::is_same<
Args...,
typename std::add_lvalue_reference<foo>::type
>::value
>::type
>
foo(Args&&... args)
: impl(std::forward<Args>(args)...)
{
std::cout << "uref" << std::endl;
}
(Также в LWS.)
EDIT: Я обнаружил, что Р. Мартиньо Фернандес писал о вариации этой проблемы в 2012 году: http://flamingdangerzone.com/cxx11/2012/06/05/is_related.html