Вывод типа C++0x путается с boost::enable_if

Я пытаюсь написать общую функцию фильтрации, которая выполняет линейную интерполяцию по заданной координате выборки в многомерном массиве (произвольный ранг). Для этого мне нужен шаблон рекурсивной функции, который проходит по всем измерениям массива, пока не найдет значение и связанный с ним тип. Я использую boost::enable_if, чтобы определить, когда прекратить перебирать измерения. Он работает нормально, пока я не попытаюсь «процедить» возвращаемое значение/тип в самую верхнюю функцию. Для этой цели я попытался использовать вывод типа C++0x, но, похоже, он плохо сочетается с boost::enable_if.

Я выделил проблему до следующего:

template< typename T, std::size_t I >
auto test(const T &t) -> typename boost::enable_if_c< (I == 0), typename T::value_type >::type
{
    return t[0];
}

template< typename T, std::size_t I >
auto test(const T &t) -> typename boost::enable_if_c< (I > 0), decltype(test< T, I - 1 >(T())) >::type
{
    return test< typename T::value_type, std::size_t(I - 1) >(t[0]);
}

Компилятор (GCC 4.6) жалуется на следующий код:

typedef std::array< std::array< float, 1 >, 1 > myarray;
myarray ma;
std::cout << typeid (test< myarray, 1 >(ma)).name() << std::endl;

Сообщение об ошибке:

error: conversion from 'boost::enable_if_c<true, float>::type' to non-scalar type 'boost::enable_if_c<true, std::array<float, 1u> >::type' requested

Кажется, что decltype использует возвращаемое значение из test‹ T, I >, хотя ему указано использовать значение test‹ T, I - 1 >. Любая идея, почему такое поведение происходит? А пока он думает, что я просто превращу все это в функтор...


person pmjobin    schedule 20.01.2011    source источник


Ответы (1)


Проблема в том, что вы передали T() (и T) в decltype. Типы не складываются. Это ясно видно, если вы сравните возвращаемое выражение с тем, что вы передали в decltype — они противоречивы.

template< typename T, std::size_t I >
auto test(const T &t) -> typename boost::enable_if_c< (I > 0), decltype(test< T, I - 1 >(T())) >::type
{
    return test< typename T::value_type, std::size_t(I - 1) >(t[0]);
}

decltype: test<T

return expression: test< typename T::value_type

При определении прямых функций, подобных этой, выражение decltype, используемое для определения возвращаемого типа, почти всегда должно быть точно таким же, как фактическое возвращаемое выражение.

Изменить: мне нужно добавить, что вы не должны передавать значения r, когда на самом деле вы будете передавать значения l, особенно в шаблоны, поскольку вы вполне можете получить разные результаты.

person Puppy    schedule 20.01.2011