Шаблон выводится как неправильный тип с переменной шаблона

Итак, у меня есть следующий тестовый код:

struct empty_value{
    template<typename T>
    T as(){ return T(0); }
};

template<typename T, typename U, typename F>
auto empty_func(empty_value lhs, empty_value rhs, F f) -> decltype(f(lhs.as<T>(), rhs.as<U>())){
    return f(lhs.as<T>(), rhs.as<U>());
}

template<typename T, typename U, template<typename, typename> class F>
static auto bind_empty_f = std::bind(empty_func<T, U, F<T, U>>, std::placeholders::_1, std::placeholders::_2, F<T, U>{});

template<typename F>
void other_test_func(F&&){}

template<typename T, typename U, template<typename, typename> class F>
void test_func(){
    other_test_func(bind_empty_f<T, U, F>);
}

template<typename T, typename U>
struct my_add{
    decltype(auto) operator()(T lhs, U rhs){ return lhs + rhs; }
};

int main(){
    test_func<float, int, my_add>();
}

Что происходит от того, над чем я на самом деле работал. Проблема возникает на линии bind_empty_f, Но только когда оно передается other_test_func, Когда я пытаюсь присвоить его обычной переменной, как это:

int main(){
    auto var = bind_empty_f<float, int, my_add>;
}

Все очень весело. Но если я позвоню test_func который пытается передать его other_test_func Я получаю ошибку, что базовый тип возвращается std::bind не может быть преобразован в float, Поэтому он пытается преобразовать его в возвращаемое значение фактической функции. Я не могу понять почему. Куда я передаю возвращаемое значение функции?


РЕДАКТИРОВАТЬ

если я вызову функцию после установки локальной переменной в значение bind_empty_f сначала он компилируется:

int main(){
    auto var = bind_empty_f<float, int, my_add>;
    test_func<float, int, my_add>;
}

Таким образом, проблема должна быть связана со статической инициализацией ошибки компилятора.

EDIT2

Как указано в комментариях, этот точный пример компилируется с другими компиляторами, но не с оригинальным протестированным компилятором (GCC 5.2.0).

Это ошибка в GCC 5.2 или в любом другом протестированном компиляторе.

Поэтому я думаю, что возникает вопрос, является ли этот стандартный код соответствия?

1 ответ

Решение

Вот минимальный пример вашей проблемы:

template<class T> struct tag {};

template<typename T>
static auto bind_empty_f = tag<T>{};

template<typename T>
decltype(bind_empty_f<T>) test_func(){
  return 3.14f;
}

тогда мы просто test_func<float>() и он возвращается 3.14f, Если мы test_func<int>() это возвращается 3,

Если мы сначала сделаем bind_empty_f<float>вместо test_func<float> генерирует ошибку.

Тип выведенный для bind_empty_f<T> когда он вызывается в другом шаблоне установлен на T а не к типу правой части выражения.

Если вы вызываете его напрямую, а тип еще не был вычислен (кажется, что кэш), то выводится правильный тип, и мой test_func не удается построить (как он пытается преобразовать 3.14f к bind Тип выражения и не удается).

Это определенно проблема с компилятором. Вы можете обойти это, заменив auto в bind_empty_f с std::decay_t<decltype(stuff_on_rhs)>,

Обратите внимание, что есть некоторые проблемы с некоторыми из ваших выражений связывания, но они не являются центральными для этой проблемы.

живой пример компиляции (неправильно), живой пример не компиляции (правильно).

Другие вопросы по тегам