должна ли ошибка вывода возвращаемого типа быть ошибкой замены?

Основываясь на моем тесте, ошибка вывода возвращаемого типа кажется ошибкой компиляции, а не ошибкой замены. В следующем примере выдается ошибка на clang3.4 с параметром -std=c++1y.

#include <type_traits>

auto f = [](auto x){return x*2;};

template < typename X, typename=decltype(f(std::declval<X>())) >
std::true_type test_impl(int);

template < typename >
std::false_type test_impl(...);

template < typename T >
using test = decltype(test_impl<T>(0));

struct A{};

int main(int argc, const char * argv[])
{
   static_assert(not test<A>{},"");
   return 0;
}

Ошибка гласит:

main.cpp:3:29: error: invalid operands to binary expression ('A' and 'int')
auto f = [](auto x){return x*2;};

Чтобы получить ошибку замены, мне пришлось изменить f на

auto f = [](auto x) ->decltype(x*2) {return x*2;};

путем повторения оператора return в завершающем decltype.

Но разве смысл автоматического вывода возвращаемого типа (как в лямбда-выражениях, так и в обычных функциях в С++ 14) не заключается в том, чтобы исключить подобное повторение кода?

У кого-нибудь есть лучший способ обойти это?

Спасибо.


person Hui    schedule 21.06.2014    source источник
comment
Но разве смысл автоматического вывода возвращаемого типа (как в лямбда-выражениях, так и в обычных функциях в С++ 14) не состоит в том, чтобы исключить подобное повторение кода? Нет, проблема IIRC в том, что вам пришлось в противном случае создайте экземпляр всей функции, просто чтобы увидеть, применяется ли SFINAE (и SFINAE применяется до разрешения перегрузки). IIRC есть краткое обсуждение в предложении о вычете возвращаемого типа.   -  person dyp    schedule 22.06.2014
comment
См., например. stackoverflow.com/q/17608637, который можно было бы легко найти, выполнив поиск вывода типа возвращаемого значения SFINAE   -  person dyp    schedule 22.06.2014
comment
Для хорошего обходного пути нам, возможно, придется подождать Concepts (Lite).   -  person dyp    schedule 22.06.2014
comment
но даже с концепциями мы все равно в конечном итоге повторяем код при определении ограничения, верно?   -  person Hui    schedule 25.06.2014
comment
С помощью концепций вы должны классифицировать эти ограничения. Вам не нужно будет повторять код для [](auto x) { return x*2; } и [](auto x) { return x*5; }, а лучше написать концепцию/ограничение, которое требует, чтобы тип можно было умножить на целочисленные типы. Я не уверен в синтаксисе, возможно, это будет что-то вроде [](IntMultipliable x) { return x*5; }   -  person dyp    schedule 25.06.2014