Как я могу запретить вызовы 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");
}