Не может быть друга с авто - PullRequest
1 голос
/ 03 мая 2011
    struct X
    {

    private:
        int value_;
    public:
        X():value_(int())
        {}
        X(int value):value_(value)
        {}
        friend
            //int operator+(X lhs, X rhs);//THIS WILL WORK  
//BUT THE ONE BELOW WON'T
        auto operator+(const X& lhs, const X& rhs)->decltype(lhs.value_ + rhs.value_);

    };


    auto operator+(const X& lhs, const X& rhs)->decltype(lhs.value_ + rhs.value_)
    {//If I change return type to "not auto" there is no problem with friendship
        return lhs.value_ + rhs.value_;
    }

    int main(int argc, char* argv[])
    {
        X a(5);
        X b(6);
        cout << a + b;
        return 0;
    }

Невозможно объявить дружбу с оператором + в сценарии, когда возвращаемым типом является auto.Любое решение для этого?

Ответы [ 3 ]

1 голос
/ 03 мая 2011

Это работает с g ++ 4.5.1:

class X {
   ...


    friend auto operator+( const X & a, const X & b )->decltype( X::value_ + X::value_  );
};

auto operator+( const X & a, const X & b )->decltype( X::value_ + X::value_) {
    return a.value_ + b.value_;
}
1 голос
/ 03 мая 2011

Похоже, что ошибка компилятора, а не что-то преднамеренное (какой компилятор? Подумайте о регистрации ошибки). Однако вы всегда можете сделать некрасивую альтернативу, описанную в спецификации для auto, с функциями (конечно, избегая этого, это мотивация для нового синтаксиса, но если он не работает ...), а именно:

decltype((*(X*)0).value_ + (*(X*)0).value_)

У вас одинаковый X с обеих сторон, так что вы можете сделать typedef в X, чтобы вам не приходилось печатать это отвратительно как в объявлении, так и в определении оператора.

(Правка) В случаях, когда у вас нет одинакового X с обеих сторон, вы все равно можете разложить объявление так, чтобы оно не было слишком ужасным, подготовив шаблон (черту) с decltype и используя его для объявления оператора. , Что-то вроде:

template <typename X, typename Y>
struct PlusType {
    typedef decltype((*(X*)0).value_ + (*(Y*)0).value_) Type;
}

template <typename X, typename Y>
PlusType<X, Y>::Type operator+(X &x, Y &y);
0 голосов
/ 03 мая 2011

По моему мнению, в вашей ситуации использование auto не имеет особого смысла, вам, вероятно, лучше сказать, что оператор возвращает int.

Проблема здесь в том, что для возможности записи rhs.value_ rhs должен быть экземпляром полного типа. Тип X считается завершенным после закрытия} класса. Так что компилятор справедливо жалуется.

EDIT3:

Поскольку мне кажется, что приведенное выше объяснение не было полным и могло привести к путанице.

struct X
{

   //code ommited for brevity...
   //at this line one has decltype(lhs.value_ + rhs.value_) where 
   //lhs and rhs are of type X however the X type is not yet complete. 
   //The compiler has to however determine the type of the friend including 
   //the return type...
   friend auto operator+(const X& lhs, const X& rhs)-> decltype(lhs.value_ + rhs.value_);
};

EDIT:

Для обсуждения VS2010, относящегося к decltype, который объясняет, почему это так, как в VS2010, а также объясняет, почему это стандартная компиляция, как в VS2010, вы можете посмотреть здесь :

Мой первый вариант - сбросить авто. Однако, предполагая, что вы предоставили более простой пример для иллюстрации, и в вашем реальном случае auto действительно имеет смысл, вы можете попробовать:

struct X
{
private:
    int value_;
public:
    X() : value_(int()) { }

    X(int value):value_(value) { }

    template <typename T>
    auto operator+(const T& rhs) -> decltype(value_ + rhs.value_)
    {
        return value_ + rhs.value_;
    }
};

int main(int argc, char* argv[])
{
    X a(5);
    X b(6);
    std::cout << a + b;

    return 0;
}

EDIT2:

Для полноты (и чтобы проиллюстрировать это не проблема с auto и friend, а скорее попытка использовать неполный тип, рассмотрите следующий код (который также дает то, что вы хотите, но искаженным образом не рекомендуется :-)):

#include <iostream>

struct X
{
public:
        X() : value_(int())     { }

        X(int value):value_(value) { }

        int value_;

};

struct A : public X
{
        friend auto operator+(const X& lhs, const X& rhs) -> decltype(lhs.value_ + rhs.value_);
};

auto operator+(const X& lhs, const X& rhs) -> decltype(lhs.value_ + rhs.value_)
{
        return lhs.value_ + rhs.value_;
}

int main(int argc, char* argv[])
{
        X a(5);
        X b(6);
        std::cout << a + b;

        return 0;
}

Код компилируется нормально в VS2010 и gcc-4.5.1

...