我想将重载函数传递给std::for_each()算法.例如,
class A {
void f(char c);
void f(int i);
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), f);
}
};
Run Code Online (Sandbox Code Playgroud)
我期望编译器f()通过迭代器类型来解析.显然,它(GCC 4.1.2)没有这样做.那么,我该如何指定f()我想要的?
你有没有恨它
class Foobar {
public:
Something& getSomething(int index) {
// big, non-trivial chunk of code...
return something;
}
const Something& getSomething(int index) const {
// big, non-trivial chunk of code...
return something;
}
}
Run Code Online (Sandbox Code Playgroud)
我们无法使用另一个方法实现这两种方法,因为您无法const从const版本中调用非版本(编译器错误).演员将被要求const从非const一个版本调用该版本.
有没有一个真正优雅的解决方案,如果没有,最接近一个?
我正在实现一个具有STL类接口的自定义容器.我必须提供一个常规迭代器和一个const迭代器.两个版本的迭代器的大多数代码都是相同的.我怎样才能避免这种重复?
例如,我的容器类是Foo,我正在实现FooIterator和FooConstIterator.两个迭代器都必须提供operator++()相同的方法.
我的问题类似于如何删除类似的const和非const成员函数之间的代码重复?但是那个问题的答案特定于const和非const方法,尤其是访问器.我没有看到这可能会如何推广到迭代器问题.
我应该FooIterator从FooConstIterator其他非const方法派生并扩展它吗?这要么导致虚拟方法或方法隐藏,这在这里似乎不合适.
也许FooIterator应该包含一个FooConstIterator.虽然这种方法确实减少了实现重复,但它似乎重新引入了许多样板方法定义.
是否有聪明的模板技术从单个定义生成两个迭代器?或许有一种方法 - 颤抖 - 使用预处理器来消除这些几乎相同的类.
我已经尝试查看我的本地STL实现,看看它是如何处理它的.有很多辅助类,我在设计中遇到了麻烦,但看起来功能很简单.
在以前的项目中,我的自定义容器是在标准STL容器之上构建的,所以我不必提供自己的迭代器.在这种情况下,这不是一个选项.
我已经教了很多年的C++编程课程,向学生解释的最棘手的事情之一是const重载.我通常使用类似矢量的类及其operator[]函数的示例:
template <typename T> class Vector {
public:
T& operator[] (size_t index);
const T& operator[] (size_t index) const;
};
Run Code Online (Sandbox Code Playgroud)
我很难解释为什么需要两个版本的operator[]函数,但在试图解释如何将两个实现统一起来时,我常常发现自己浪费了很多时间使用语言arcana.问题是,我知道如何使用const_cast/ static_casttrick 实现其中一个函数的唯一好的,可靠的方法是:/ trick:
template <typename T> const T& Vector<T>::operator[] (size_t index) const {
/* ... your implementation here ... */
}
template <typename T> T& Vector<T>::operator[] (size_t index) {
return const_cast<T&>(static_cast<const Vector&>(*this)[index]);
}
Run Code Online (Sandbox Code Playgroud)
这种设置的问题在于解释起来非常棘手,而且根本不明显.当你把它解释为"转换为const,然后调用const版本,然后去掉constness"时,它会更容易理解,但实际的语法是可怕的.解释什么const_cast是,为什么它的适当位置,以及它为什么几乎普遍不恰当的其他地方通常需要我五至十分钟的演讲时间,而这整个表达式的决策意识往往需要比之间的差异更多的精力const T*和T* const.我觉得学生需要了解const-overloading以及如何在不必要地复制两个函数中的代码的情况下完成它,但是这个技巧在C++入门编程课程中似乎有些过分.
我的问题是 - 是否有一种更简单的方法来实现相互const重叠的功能?或者是否有更简单的方法向学生解释现有技巧?
为了使这个代码与C++ 11引用限定符按预期工作,我必须引入一个std::move(*this)听起来不对的代码.
#include<iostream>
struct A{
void gun() const&{std::cout << "gun const&" << std::endl;}
void gun() &&{std::cout << "gun&&" << std::endl;}
void fun() const&{gun();}
void fun() &&{std::move(*this).gun();} // <-- is this correct? or is there a better option
};
int main(){
A a; a.fun(); // prints gun const&
A().fun(); // prints gun&&
}
Run Code Online (Sandbox Code Playgroud)
有些事情听起来不对劲.有std::move必要吗?这是推荐使用吗?目前,如果我不使用它,我会遇到gun const&两种情况,这不是预期的结果.
(似乎*this总是隐式和左值引用,这是有道理的,但然后是逃避使用的唯一方法move)
用clang 3.4和测试gcc 4.8.3.
编辑:这是我从@hvd回答中理解的:
1)std::move(*this)在语法和概念上是正确的
2)但是,如果 …
使用一个优于另一个是否有任何优势:
class Foo
{
public:
const int& get() const
{
// stuff here
return myInt;
}
int& get()
{
return const_cast<int&>(static_cast<const Foo*>(this)->get());
}
};
Run Code Online (Sandbox Code Playgroud)
要么
class Foo
{
public:
int& get()
{
// stuff here
return myInt;
}
const int& get() const
{
return const_cast<Foo*>(this)->get();
}
};
Run Code Online (Sandbox Code Playgroud)
我只使用了第一个,但我刚看到第二个用在某个地方,所以我很想知道.
注释// stuff here可能是一个非平凡的检查,如检索表的索引,以便返回表的成员的引用(例如:),myInt = myTable[myComputedIndex];所以我不能只是公开它.因此,表和任何成员都不是const.
最近我发现了一段有效执行以下操作的C++代码:
char* pointer = ...;
const char* constPointer = const_cast<const char*>( pointer );
Run Code Online (Sandbox Code Playgroud)
显然作者认为这const_cast意味着"添加const",但实际上const也可以隐含地添加:
const char* constPointer = pointer;
Run Code Online (Sandbox Code Playgroud)
有没有当我真的有任何情况下const_cast ,以一个指针到常量(const_cast<const Type*>如上面的例子)?
我有类似这样的代码:
#include <string>
class A{
public:
std::string &get(){
return s;
}
const std::string &get() const{
return s;
}
std::string &get_def(std::string &def){
return ! s.empty() ? s : def;
}
// I know this might return temporary
const std::string &get_def(const std::string &def) const{
return ! s.empty() ? s : def;
}
private:
std::string s = "Hello";
};
Run Code Online (Sandbox Code Playgroud)
我想知道是否有简单的方法来避免get()函数中的代码重复?
我正在考虑关于const和非const类方法的这个问题.首选答案取自Scott Meyers的Effective C++,其中非const方法是根据const方法实现的.
进一步扩展,如果方法返回迭代器而不是引用,如何减少代码重复?修改链接问题中的示例:
class X
{
std::vector<Z> vecZ;
public:
std::vector<Z>::iterator Z(size_t index)
{
// ...
}
std::vector<Z>::const_iterator Z(size_t index) const
{
// ...
}
};
Run Code Online (Sandbox Code Playgroud)
我不能在const方法方面实现非const方法,因为不使用distance()/ advance()技术就无法直接从const_iterator转换为迭代器.
在这个例子中,因为我们使用std :: vector作为容器,所以实际上可以从const_iterator转换为迭代器,因为它们很可能被实现为指针.我不想依赖于此.有更通用的解决方案吗?
在此示例代码中,两个process()函数内的循环是重复的.唯一的区别是一个是const,另一个不是.
有没有办法删除代码重复,这样循环只存在一次?这只是一个例子,但在实际代码中循环非常复杂,因此出于维护原因,我只希望循环存在一次.
#include <iostream>
#include <vector>
typedef unsigned int Item;
typedef std::vector<Item *> Data;
struct ReadOnlyAction {
void action(const Item *i)
{
// Read item, do not modify
std::cout << "Reading item " << *i << "\n";
}
};
struct ModifyAction {
void action(Item *i)
{
// Modify item
std::cout << "Modifying item " << *i << "\n";
(*i)++;
}
};
void process(Data *d, ModifyAction *cb) {
// This loop is actually really complicated, and there …Run Code Online (Sandbox Code Playgroud)