C++:从模板化基类覆盖函数

标签 c++ templates inheritance overriding

这是简单的版本。下面,我将全面解释真实世界的用例。

我有两个类:

template<class T>
class Base {
protected:
    virtual void foo();
    std::map<std::string*, T*> things;
};

class Derived : public Base<int> {
protected:
    void foo();
};

template<class T>
void Base<T>::foo() {
    for (auto itr = things.begin(); itr < things.end(); ++itr) {
    }
}

void Derived::foo() {
    for (auto itr = things.begin(); itr < things.end(); ++itr) {
    }
}

我在 fooDerived 实现中遇到了 for 循环条件的问题:

example.cpp: In member function ‘virtual void Derived::foo()’:
example.cpp:23:53: error: no match for ‘operator<’ in ‘itr < ((Derived*)this)->Derived::<anonymous>.Base<int>::things.std::map<_Key, _Tp, _Compare, _Alloc>::end<std::basic_string<char>*, int*, std::less<std::basic_string<char>*>, std::allocator<std::pair<std::basic_string<char>* const, int*> > >()’
example.cpp:23:53: note: candidates are:
In file included from /usr/include/c++/4.7/string:54:0,
                 from example.cpp:2:
/usr/include/c++/4.7/bits/basic_string.h:2590:5: note: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const _CharT*, const std::basic_string<_CharT, _Traits, _Alloc>&)
/usr/include/c++/4.7/bits/basic_string.h:2590:5: note:   template argument deduction/substitution failed:
example.cpp:23:53: note:   mismatched types ‘const _CharT*’ and ‘std::_Rb_tree_iterator<std::pair<std::basic_string<char>* const, int*> >’
In file included from /usr/include/c++/4.7/string:54:0,
                 from example.cpp:2:
/usr/include/c++/4.7/bits/basic_string.h:2578:5: note: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const std::basic_string<_CharT, _Traits, _Alloc>&, const _CharT*)
/usr/include/c++/4.7/bits/basic_string.h:2578:5: note:   template argument deduction/substitution failed:
example.cpp:23:53: note:   ‘std::_Rb_tree_iterator<std::pair<std::basic_string<char>* const, int*> >’ is not derived from ‘const std::basic_string<_CharT, _Traits, _Alloc>’
In file included from /usr/include/c++/4.7/string:54:0,
                 from example.cpp:2:
/usr/include/c++/4.7/bits/basic_string.h:2566:5: note: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const std::basic_string<_CharT, _Traits, _Alloc>&, const std::basic_string<_CharT, _Traits, _Alloc>&)
/usr/include/c++/4.7/bits/basic_string.h:2566:5: note:   template argument deduction/substitution failed:
example.cpp:23:53: note:   ‘std::_Rb_tree_iterator<std::pair<std::basic_string<char>* const, int*> >’ is not derived from ‘const std::basic_string<_CharT, _Traits, _Alloc>’
In file included from /usr/include/c++/4.7/map:62:0,
                 from example.cpp:1:
/usr/include/c++/4.7/bits/stl_multimap.h:822:5: note: template<class _Key, class _Tp, class _Compare, class _Alloc> bool std::operator<(const std::multimap<_Key, _Tp, _Compare, _Alloc>&, const std::multimap<_Key, _Tp, _Compare, _Alloc>&)
/usr/include/c++/4.7/bits/stl_multimap.h:822:5: note:   template argument deduction/substitution failed:
example.cpp:23:53: note:   ‘std::_Rb_tree_iterator<std::pair<std::basic_string<char>* const, int*> >’ is not derived from ‘const std::multimap<_Key, _Tp, _Compare, _Alloc>’
In file included from /usr/include/c++/4.7/map:61:0,
                 from example.cpp:1:
/usr/include/c++/4.7/bits/stl_map.h:906:5: note: template<class _Key, class _Tp, class _Compare, class _Alloc> bool std::operator<(const std::map<_Key, _Tp, _Compare, _Alloc>&, const std::map<_Key, _Tp, _Compare, _Alloc>&)
/usr/include/c++/4.7/bits/stl_map.h:906:5: note:   template argument deduction/substitution failed:
example.cpp:23:53: note:   ‘std::_Rb_tree_iterator<std::pair<std::basic_string<char>* const, int*> >’ is not derived from ‘const std::map<_Key, _Tp, _Compare, _Alloc>’
In file included from /usr/include/c++/4.7/map:60:0,
                 from example.cpp:1:
/usr/include/c++/4.7/bits/stl_tree.h:873:5: note: template<class _Key, class _Val, class _KeyOfValue, class _Compare, class _Alloc> bool std::operator<(const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&, const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&)
/usr/include/c++/4.7/bits/stl_tree.h:873:5: note:   template argument deduction/substitution failed:
example.cpp:23:53: note:   ‘std::_Rb_tree_iterator<std::pair<std::basic_string<char>* const, int*> >’ is not derived from ‘const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/stl_tree.h:63,
                 from /usr/include/c++/4.7/map:60,
                 from example.cpp:1:
/usr/include/c++/4.7/bits/stl_iterator.h:1063:5: note: template<class _Iterator> bool std::operator<(const std::move_iterator<_Iterator>&, const std::move_iterator<_Iterator>&)
/usr/include/c++/4.7/bits/stl_iterator.h:1063:5: note:   template argument deduction/substitution failed:
example.cpp:23:53: note:   ‘std::_Rb_tree_iterator<std::pair<std::basic_string<char>* const, int*> >’ is not derived from ‘const std::move_iterator<_Iterator>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/stl_tree.h:63,
                 from /usr/include/c++/4.7/map:60,
                 from example.cpp:1:
/usr/include/c++/4.7/bits/stl_iterator.h:1057:5: note: template<class _IteratorL, class _IteratorR> bool std::operator<(const std::move_iterator<_Iterator>&, const std::move_iterator<_IteratorR>&)
/usr/include/c++/4.7/bits/stl_iterator.h:1057:5: note:   template argument deduction/substitution failed:
example.cpp:23:53: note:   ‘std::_Rb_tree_iterator<std::pair<std::basic_string<char>* const, int*> >’ is not derived from ‘const std::move_iterator<_Iterator>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/stl_tree.h:63,
                 from /usr/include/c++/4.7/map:60,
                 from example.cpp:1:
/usr/include/c++/4.7/bits/stl_iterator.h:349:5: note: template<class _IteratorL, class _IteratorR> bool std::operator<(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_IteratorR>&)
/usr/include/c++/4.7/bits/stl_iterator.h:349:5: note:   template argument deduction/substitution failed:
example.cpp:23:53: note:   ‘std::_Rb_tree_iterator<std::pair<std::basic_string<char>* const, int*> >’ is not derived from ‘const std::reverse_iterator<_Iterator>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/stl_tree.h:63,
                 from /usr/include/c++/4.7/map:60,
                 from example.cpp:1:
/usr/include/c++/4.7/bits/stl_iterator.h:299:5: note: template<class _Iterator> bool std::operator<(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_Iterator>&)
/usr/include/c++/4.7/bits/stl_iterator.h:299:5: note:   template argument deduction/substitution failed:
example.cpp:23:53: note:   ‘std::_Rb_tree_iterator<std::pair<std::basic_string<char>* const, int*> >’ is not derived from ‘const std::reverse_iterator<_Iterator>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:65:0,
                 from /usr/include/c++/4.7/bits/stl_tree.h:63,
                 from /usr/include/c++/4.7/map:60,
                 from example.cpp:1:
/usr/include/c++/4.7/bits/stl_pair.h:212:5: note: template<class _T1, class _T2> constexpr bool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&)
/usr/include/c++/4.7/bits/stl_pair.h:212:5: note:   template argument deduction/substitution failed:
example.cpp:23:53: note:   ‘std::_Rb_tree_iterator<std::pair<std::basic_string<char>* const, int*> >’ is not derived from ‘const std::pair<_T1, _T2>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/stl_tree.h:63,
                 from /usr/include/c++/4.7/map:60,
                 from example.cpp:1:
/usr/include/c++/4.7/bits/stl_iterator.h:838:5: note: template<class _Iterator, class _Container> bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_Iterator, _Container>&, const __gnu_cxx::__normal_iterator<_Iterator, _Container>&)
/usr/include/c++/4.7/bits/stl_iterator.h:838:5: note:   template argument deduction/substitution failed:
example.cpp:23:53: note:   ‘std::_Rb_tree_iterator<std::pair<std::basic_string<char>* const, int*> >’ is not derived from ‘const __gnu_cxx::__normal_iterator<_Iterator, _Container>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/stl_tree.h:63,
                 from /usr/include/c++/4.7/map:60,
                 from example.cpp:1:
/usr/include/c++/4.7/bits/stl_iterator.h:832:5: note: template<class _IteratorL, class _IteratorR, class _Container> bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_IteratorL, _Container>&, const __gnu_cxx::__normal_iterator<_IteratorR, _Container>&)
/usr/include/c++/4.7/bits/stl_iterator.h:832:5: note:   template argument deduction/substitution failed:
example.cpp:23:53: note:   ‘std::_Rb_tree_iterator<std::pair<std::basic_string<char>* const, int*> >’ is not derived from ‘const __gnu_cxx::__normal_iterator<_IteratorL, _Container>’

为什么这行不通,我应该如何解决?

P.S.:我知道这是使用模板特化的绝佳机会,但我认为这不适合我的用例。


这是完整的故事。

我正在制作一个包含多种类型节点的场景图。这个问题的一些重要问题是:

  1. 场景父级
  2. 场景区域
  3. 场景组
  4. 场景组件

他们各自扮演以下角色:

  • SceneParent 包含一组子模板类型 T。
  • SceneRegion 扩展 SceneParent,将 T 指定为 SceneParent
  • SceneGroup 扩展 SceneParent,将 T 指定为 SceneComponent

我要实现的功能是getVisibleChildren。给定一个视口(viewport),我想要接收一组应该渲染的 SceneComponent

SceneParent 的实现在所有 child 上递归调用:

template< class T >
void SceneParent< T >::getVisibleChildren(const util::Camera& camera,
 std::vector< SceneComponent* >& visibleChildren) const {
    if (!this->isVisible(camera)) {
        return;
    }

    // Get ids into a flat container so the next loop can be parallelized.
    std::vector< std::string* > childIds;
    for (auto itr = this->children.cbegin(); itr < this->children.cend();
     ++itr) {
        childIds.push_back(itr->first);
    }

    // TODO: parallelize this.
    for (auto itr = childIds.cbegin(); itr < childIds.cend(); ++itr) {
        this->children[*itr]->getVisibleChildren(camera, visibleChildren);
    }
}

SceneGroup 的实现将它的所有 SceneComponent 添加到累加器(假设如果一个组可见,那么它的组件也是可见的)。所以 SceneGroup 节点充当递归的基本情况:

void SceneGroup::getVisibleChildren(const util::Camera& camera,
 std::vector< SceneComponent* >& visibleChildren) const {
    if (!this->isVisible(camera)) {
        return;
    }

    // If this group is visible, assume all of its components are as well.
    for (auto itr = this->children.cbegin(); itr < this->children.cend();
     ++itr) {
        visibleChildren.push_back(itr->second);
    }
}

既然您已经在我的帖子中谈到了这一点,我假设您对我的实际应用程序感兴趣(至少是温和地),而不仅仅是它导致的编译器错误。因此,如果您愿意,请就我如何改进场景图的实现/我在处理此项目时应该注意的事项提供任何建议。

最佳答案

std::map<K, V> 的迭代器是双向迭代器。对双向迭代器使用小于运算符没有任何意义。只需使用相等或不等运算符编写循环:

for (auto itr = things.begin(); itr != things.end(); ++itr) {
}

关于C++:从模板化基类覆盖函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18819551/

相关文章:

c++ - 使用 SWIG 实现 C++ 和 Ruby 之间的多态性

c++ - 固定到核心的 FIFO 线程上的 std::promise::set_value 不会唤醒 std::future

c++ - 修改通过引用传递的变量

c++ - Flutter和Linux

c++ - 使用 OpenGL 将实心圆绘制为一个顶点数组?

javascript - 是否有一个 JQuery 插件可以让浏览器从当前位置平滑地向下滚动到 200 像素?

jQuery 模板引擎

ios - 从 C++ 类继承 NSObject

c++ - 创建基于 SFINAE 的构造函数时出现编译错误

java - 从泛型类调用枚举静态方法