Как я могу запретить вызовы const функции-члена объекта rvalue в C++ 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-reference объявление удаленной функции может использоваться для полного запрета вызовов at если векторный аргумент является значением

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 ответа

Решение

Нет, и ты не должен. Как мне поступить 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

Просто идея:

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

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

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

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

void mkvec(std::vector<std::string>& n)
{
    n.push_back("kagami");
    n.push_back("misao");
}
Другие вопросы по тегам