SFINAE enable_if для шаблона идеальной пересылки с переменным числом аргументов при константности ссылки/указателя

Я хочу создать вариативную оболочку make_shared<T> с идеальной переадресацией, но такую, которая SFINAEd в зависимости от того, принимает ли конструктор T какие-либо неконстантные аргументы ссылки/указателя. Идея состоит в том, чтобы иметь две оболочки, называемые construct и construct_nonconst, где при построении Foo(int& r) или Foo(int* r) необходимо использовать последнюю. Цель этого состоит в том, чтобы когда разработчики пишут классы, конструкторы которых требуют неконстантных параметров, они могли это сделать, но на месте вызова ясно видно, что конструкция может иметь локальные побочные эффекты.

Я просмотрел Реализация признаков вариативного типа и поиграл с is_constructible (я пытался преобразовать свои Args ... пакет параметров для всех версий const), но я не могу понять это.

Желаемый результат:

struct NonConst
{
  NonConst(int& uhOh)
  {
    uhOh = 2;
  }
};

struct Const
{
  Const(const int& noProblemo)
  {
    // ...
  }
};

struct ByValueStr
{
  ByValueStr(std::string noProblemo)
  {
    // ...
  }
};

int x = 5;
const int y = 5;
std::string s("foo")

auto nc1 = builder<NonConst>::construct(x); // this doesn't compile
auto nc2 = builder<NonConst>::construct_nonconst(x); // fine, but noticeable
auto c1 = builder<Const>::construct(x); // fine
auto c2 = builder<ByValueStr>::construct(s); // fine

person experquisite    schedule 06.05.2015    source источник
comment
Интересно, действительно ли это хорошая идея. Конструктор может не использовать указатель или ссылку для изменения референта, но функция-член может изменить его позже. В этом случае вы напрасно заставляете людей писать construct_nonconst. Разве это не намеренно и в этом случае?   -  person Brian Bi    schedule 06.05.2015
comment
Да, идея в том, что 99% всех классов будут неизменяемыми и/или ссылочно прозрачными, и должно быть очень ясно, когда это не так.   -  person experquisite    schedule 06.05.2015
comment
Я также должен добавить, что я пытался сделать это только с вариативным const Args&... , но столкнулся с проблемами с конструкторами, принимающими строки с использованием литералов char.   -  person experquisite    schedule 06.05.2015
comment
Не проще ли было бы добавить const ко всем аргументам lvalue?   -  person dyp    schedule 06.05.2015
comment
Я не уверен, я пытался добавить const к своим аргументам... при использовании is_constructible, но, похоже, это ничего не дало. Может быть, я неправильно понимаю. Универсальная ссылка с идеальной переадресацией идеальна, я просто хочу отключить ее, если есть какие-либо неконстантные указатели или ссылки (или умные указатели, если на то пошло).   -  person experquisite    schedule 06.05.2015
comment
Я имел в виду: template<class T> T const& const_if_lvalue(T& t) { return t; } template<class T> T&& const_if_lvalue(T&& t) { return move(t); } template<typename R, typename... Args> R construct(Args&&... args) { return R(const_if_lvalue(forward<Args>(args))...); }   -  person dyp    schedule 06.05.2015
comment
@dyp, похоже, это работает, но только если я добавлю enable_if к универсальной эталонной реализации const_if_lvalue, согласно stackoverflow.com/questions/7748104/ , template< class T, typename = typename std::enable_if<!std::is_reference<T>::value>::type > T&& const_if_lvalue(T&& t) { return std::move(t); }   -  person experquisite    schedule 06.05.2015
comment
Если вы хотите написать это как ответ, это работает для меня.   -  person experquisite    schedule 06.05.2015
comment
@experquisite Вы использовали template<class T> T const& const_if_lvalue(T const& t) { return t; }? Важно, чтобы параметр функции был T&, а не T const&. Какой компилятор вы использовали?   -  person dyp    schedule 06.05.2015
comment
Я использовал T& t, но получил неоднозначные ошибки перегрузки в gcc 4.8.2.   -  person experquisite    schedule 06.05.2015
comment
@experquisite Интересно. Похоже на ошибку: это работает в gcc 4.9 - вы также можете написать это самостоятельно в качестве ответа и, возможно, объяснить, как это вам поможет. Я не думаю, что полностью понял вашу первоначальную проблему.   -  person dyp    schedule 07.05.2015