Как я могу запретить вызовы const функции-члена объекта rvalue в C ++ 2011? - PullRequest
2 голосов
/ 28 апреля 2011

следующий код

#include <vector>
#include <string>
#include <iostream>

std::string const& at(std::vector<std::string> const& n, int i)
{
    return n[i];
}

std::vector<std::string> mkvec()
{
    std::vector<std::string> n;
    n.push_back("kagami");
    n.push_back("misao");
    return n;
}

int main()
{
    std::string const& s = at(mkvec(), 0);
    std::cout << s << std::endl; // D'oh!
    return 0;
}

может привести к сбою, поскольку там уже уничтожен исходный вектор. В C ++ 2011 (c ++ 0x) после введения rvalue-ссылки, объявление удаленная функция может использоваться для полного запрета вызовов at, если аргументом вектора является значение r 100 * *

std::string const& at(std::vector<std::string>&&, int) = delete;

Это выглядит хорошо, но следующий код по-прежнему вызывает сбой

int main()
{
    std::string const& s = mkvec()[0];
    std::cout << s << std::endl; // D'oh!
    return 0;
}

потому что вызовы функции-члена operator [] (size_type) const объекта rvalue все еще разрешены. Можно ли как-то запретить подобные звонки?

FIX:

Приведенные выше примеры - не то, что я делал в реальных проектах. Мне просто интересно, поддерживает ли C ++ 2011 какую-либо функцию-член, такую ​​как

class A {
    void func() rvalue; // Then a call on an rvalue object goes to this overload
    void func() const;
};

FIX:

Это здорово, но я думаю, что стандарт C ++ заходит слишком далеко в этой функции. Во всяком случае, у меня есть следующий код, скомпилированный на Clang ++ 2.9

#include <cstdio>

struct A {
    A() {}

    void func() &
    {
        puts("a");
    }

    void func() &&
    {
        puts("b");
    }

    void func() const &
    {
        puts("c");
    }
};

int main()
{
    A().func();
    A a;
    a.func();
    A const b;
    b.func();
    return 0;
}

Большое спасибо!

Ответы [ 2 ]

6 голосов
/ 28 апреля 2011

Нет, и вы не должны.Как мне сделать std::cout << at(mkvec(), 0) << std::endl;, что вполне разумно, если вы запретили мне использовать at() для временных файлов?

Хранение ссылок на временные файлы - это просто проблема, с которой, к сожалению, сталкиваются программисты C ++.


Чтобы ответить на ваш новый вопрос, да, вы можете сделать это:

class A {
    void func() &; // lvalues go to this one
    void func() &&; // rvalues go to this one
};

A a;
a.func(); // first overload

A().func(); // second overload
0 голосов
/ 28 апреля 2011

Просто идея:

Чтобы как-то отключить копирование конструктора на вектор.

vector ( const vector<T,Allocator>& x );

Неявное копирование массивов не так уж и хорошо.(интересно, почему авторы STL решили вообще определить такой ctor)

Это исправит проблемы, о которых вы упоминали, и в качестве бонуса заставит вас использовать более эффективную версию вашей функции:

void mkvec(std::vector<std::string>& n)
{
    n.push_back("kagami");
    n.push_back("misao");
}
...