【问题标题】:Template nested class of template class as parameter to fully specialized function模板类的模板嵌套类作为完全专用功能的参数
【发布时间】:2018-09-07 00:50:02
【问题描述】:

我构建了一个自定义模板化迭代器作为模板化容器的嵌套类:

template< typename T, class U, typename V >
class aContainer {
  public:
    template< bool ABool, bool BBool >
    class aIterator {
      public:
        using iterator_category = std::forward_iterator_tag;
        using value_type = T;
        using difference_type = std::ptrdiff_t;
        using referenc = T&;
        using pointer = T*;
       /** iterator related operations */
    };
  protected:
    T const * const _begin;
    T const * const _end;
  public:
    explicit aContainer( T const * const begin, std::size_t count ):
      __begin{ begin }, __end{ __begin + count } { }
    auto begin_a() const { return aIterator< true, false >{ __begin }; }
    auto end_a() const { return aIterator< true, false >{ __end }; }

    auto begin_b() const { return aIterator< false, true >{ __begin }; }
    auto end_b() const { return aIterator< false, true >{ __end }; }
};

为了匹配现有库的样式,我想将迭代器的引用传递给完全专用的模板函数:

template< typename T, template< class > class U >
T max( T* data );

template<>
int max< int, aU >( int* data ) {
  return old_c_style_max_int( data, aU< T >::size );
}

template<>
float max< float, bU >( float* data ) {
  return old_c_style_max_float( data, bU< T >::size );
}

也许这看起来有点奇怪,但这很好地掩盖了不同的旧 c 风格的函数调用。

U 类是一个辅助结构,创建一个特定的上下文(或风格)。容器及其迭代器需要该上下文。

template< typename T >
class aU {
  using constexpr std::size_t size = 10;
  using value_t = T;
  /** ... */
};
template< typename T >
class bU {
  using constexpr std::size_t size = 20;
  using value_t = T;
  /** ... */
};

我想要实现的是将迭代器作为参数传递给函数:

/* ... */
aContainer< int, aClass, bool > container( start );
auto iterator = container.begin_a();
for( ; iterator != container.end_a(); ++iterator ) {
  foo< int, aClass >( iterator );
}
/* ... */

这甚至可能吗?我的猜测被编译器拒绝了:/ 我认为,包装结构可能是一种可能的解决方案,但我想避免这种情况。也是一个迭代器基类,隐藏模板迭代器类似乎可行,但从概念的角度来看并不可取。

【问题讨论】:

  • 只有当你的特化 foo 声明它的参数类型与传入的迭代器的类型完全匹配时才有可能。也就是说,特化类似于 template&lt;&gt; void foo&lt; int, aClass &gt;(aContainer&lt;int, aClass, char *&gt;::aIterator&lt;true,false&gt; param);。跨度>
  • 是的,但这不是我想要做的:D 我的意思是,这种方式迫使我进行大量的代码重复。没有另一个不错的 c++17 hack 吗? :D
  • 重载通常比模板函数的完全特化更受欢迎......老实说,我真的不明白为什么你希望这些函数成为完全的模板特化(也许你可以告诉我们为什么?) .通常你会有一个template&lt;class T, class U, class V, bool A, bool B&gt; void foo(typename aContainer&lt;T, U, V&gt;::template aIterator&lt;A, B&gt;) 通用模板函数,然后为每个特殊情况重载。
  • 旁注:包含双下划线的标识符保留用于实现。
  • 嗯,包装实际调用的函数,取决于从给定模板推导出的类型。

标签: c++ c++11 templates iterator c++17


【解决方案1】:

你可以给foo添加另一个类型参数:

template<typename T, class U, typename Itr> void foo(Itr itr);

如果你想强调TU 和迭代器是通过aContainer 耦合的......好吧,你仍然需要一个额外的参数......一些额外的参数:

template<typename T, class U, bool flag, bool a, bool b> void foo(typename aContainer<T, U, flag>::template aIterator<a, b> itr);

但这一次你需要给你的编译器关于外部类型的完整信息,换句话说,也提供flag(迭代器自己的参数ab会被推导出来):

foo<int, aClass, true>( iterator );

【讨论】:

  • 感谢您的回复。我希望我可以避免那个额外的模板参数,因为它是在其他地方指定的。但据我所知,自动说明符不适用于专业化。所以我想,这将是一种合格的方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-26
  • 1970-01-01
  • 1970-01-01
  • 2017-07-03
  • 2015-03-01
相关资源
最近更新 更多