Аргументы функции шаблона не выполняют никаких неявных преобразований. - PullRequest
4 голосов
/ 22 июня 2011

По какой-то странной причине я не могу получить аргументы шаблона в этом фрагменте кода для неявного приведения к совместимому типу.

#include <type_traits>

template <typename T, unsigned D>
struct vec;

template <>
struct vec<float, 2> {
    typedef float scalar;
    static constexpr unsigned dimension = 2;

    float x, y;
    float&       operator[] (unsigned i)       { return (&x)[i]; }
    float const& operator[] (unsigned i) const { return (&x)[i]; }
};


template <typename L, typename R>
struct add;

template <typename L, typename R, unsigned D>
struct add<vec<L, D>, vec<R, D>> {
    typedef vec<L, D> left_type;
    typedef vec<R, D> right_type;
    typedef vec<typename std::common_type<L, R>::type, D> return_type;

    add(left_type l, right_type r)
        : left(l),
          right(r)
    {}

    operator return_type() const
    {
        return_type result;
        for (unsigned i = 0; i < D; ++i)
            result[i] = left[i] + right[i];
        return result;
    }

    left_type  left;
    right_type right;
};


template <typename L, typename R, unsigned D>
add<vec<L, D>, vec<R, D>>
operator+(vec<L, D> const& lhs, vec<R, D> const& rhs)
{
    return {lhs, rhs};
}


int main()
{
    vec<float, 2> a, b, c;
    vec<float, 2> result = a + b + c;
}

Сбой с:

prog.cpp: In function 'int main()':
prog.cpp:55:36: error: no match for 'operator+' in 'operator+ [with L = float, R = float, unsigned int D = 2u](((const vec<float, 2u>&)((const vec<float, 2u>*)(& a))), ((const vec<float, 2u>&)((const vec<float, 2u>*)(& b)))) + c'

Так что, если я прав, компилятор должен увидеть код в основной функции следующим образом:

  • ((a + b) + c)
  • вычислить a + b
  • приведите результат a + b из add<...> в vec<float, 2>, используя оператор преобразования в add<...>
  • вычислить (a + b) + c

Но это никогда не делает неявное приведение. Если я явно приведу результат (a + b) к vec, код работает нормально.

Ответы [ 2 ]

5 голосов
/ 22 июня 2011

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

Proto - это фреймворк для построения специфичных для домена встроенных языков в C ++.Он предоставляет инструменты для конструирования, проверки типов, преобразования и выполнения шаблонов выражений .В частности, Proto предоставляет:

  • Структура данных дерева выражений.
  • Механизм для придания выражениям дополнительных поведений и членов.
  • Перегрузки операторов для построения дерева извыражение.
  • Утилиты для определения грамматики, которой должно соответствовать выражение.
  • Расширяемый механизм для немедленного выполнения шаблона выражения.
  • Расширяемый набор преобразований дерева вприменяется к деревьям выражений.

См. также серию статей Expressive C ++ автора библиотеки, которые более или менее служат (превосходным) всесторонним повышением. Прото учебник.

2 голосов
/ 22 июня 2011

Большинство преобразований не используются при выводе аргументов шаблона.

Вы полагаетесь на вывод аргументов шаблона при вызове вашей перегрузки operator+: она вызывается только тогда, когда оба аргумента имеют тип vec<...>, но когдавы пытаетесь назвать его левым аргументом типа add<...>.Компилятор не может понять, что вы на самом деле имеете в виду, что эта перегрузка вызывается (и не может быть угадана), следовательно, ошибка.

...