Я писал код на C ++ для векторной математики. Обязательно просто тонкую обертку вокруг std::array
пример. Я хотел перегрузить не член begin()
функция для возврата итератора в начало резервного массива. Для этого я написал простую функцию друга с auto
тип возврата и конечный тип возврата, используя decltype
который просто перенаправил вызов в переменную-член.
Это не скомпилируется, и я не мог понять, почему. Я начал возиться с небольшим примером и обнаружил, что следующий код компилируется в G ++ 4.7, но не в последней версии Visual Studio 2012 Professional.
#include <iostream>
#include <array>
template <typename T, size_t size>
class MyClass {
private:
std::array<T, size> elts;
public:
friend auto begin(MyClass &a) -> decltype (std::begin(a.elts)) {
return std::begin(a.elts);
}
};
int main(void) {
MyClass<int, 8> instance;
auto it = begin(instance);
std::cout << *it << std::endl;
return 0;
}
Странно было то, что этот код компилируется только в G ++, если частное объявление elts
до объявления begin()
функция.
В любом случае, какой компилятор здесь? Visual Studio или G ++?
редактировать: Ошибка компиляции, которую выдал VS2012 error C2228: left of '.elts' must have class/struct/union
Определение шаблона класса MyClass
не завершено к тому времени, когда вы используете выражение std::begin(a.elts)
Я думаю, у VC есть основания жаловаться. Вы не можете использовать operator .
по неполному типу.
В любом случае вы можете обойти это, используя следующее:
#include <iostream>
#include <array>
template <typename T, size_t size>
class MyClass
{
// ...
friend typename std::array<T, size>::iterator begin(MyClass &a)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
return std::begin(a.elts);
}
};
Других решений пока нет …