代码之家  ›  专栏  ›  技术社区  ›  PierreBdR

C++模板中引用的处理

  •  2
  • PierreBdR  · 技术社区  · 15 年前

    我目前有一个函数模板,作为参考,它在本质上相当于:

    template <typename T>
    void f(T& t)
    {
       t = T();
    }
    

    现在,我可以打电话给:

    int a;
    f(a);
    

    初始化变量A。 我甚至可以做到:

    std::vector<int> a(10);
    f(a[5]);
    

    但是,这将失败:

    std::vector<bool> a(10);
    f(a[5]);
    

    原因是 a[5] 返回具有引用语义但不是引用的对象。所以我需要能够写:

    template <typename T>
    void f(T a)
    {
      a = T();
    }
    

    但是如果我添加这个新模板并尝试编译第一个示例(使用int),我会得到以下错误:

    test_multi_tmpl.cc: In function ‘int main()’:
    test_multi_tmpl.cc:20: error: call of overloaded ‘f(int&)’ is ambiguous
    test_multi_tmpl.cc:6: note: candidates are: void f(T&) [with T = int]
    test_multi_tmpl.cc:12: note:                 void f(T) [with T = int]
    

    有什么解决办法吗?我不想超载 f 只是为了 std::vector<bool>::reference 因为这个结构可能出现在其他地方…

    4 回复  |  直到 15 年前
        1
  •  4
  •   James    15 年前

    我想专门为 std::vector<bool>::reference 是你唯一的选择。

    注意使用 std::vector<bool> 一开始可能是个坏主意 std::vector<bool> 对于C++语言的未来版本,专业化是被禁止的,所以你可以使用它。 std::deque<bool> 相反。

        2
  •  1
  •   Leandro T. C. Melo    15 年前

    我不确定你是否已经知道这件事…

    专门化std::vector是 真的是一个STL容器,因为它 满足必要的要求。特别是,不可能创建满足 STL concepts 因为引用语义(不能伪造引用)。检查 this article 更多信息。(也就是说,在自动引用的情况下,应该有一个编译器指令来提供对STD::在未来C++标准中的向量的控制)。

    解决问题的一个简单方法是通过重载函数 F 对于这个特定类型(以及其他类型,如果它们出现并且不多的话)。注意这是一个 超载 专业化 . 你也可以查一下这个 why not specialize function templates .

    
    void f(std::vector<bool>::reference t)
    {
      /* ... */
    }
    
        3
  •  1
  •   Dean Michael    15 年前

    有两种方法可以做到这一点,一种是,正如您所建议的,专门用于 std::vector<bool>::reference .另一种是利用类型特征进行调度。

    template <class T>
    void f (T& t) {
      f_impl(t, is_reference_wrapper_type<T>());
    }
    
    template <class T>
    void f_impl(T& t, mpi::false_) {
      t = T();
    }
    
    template <class T>
    void f_impl(T& t, mpi::true_) {
      // do nothing, or voodoo here
    }
    

    注意,上面的代码是未经测试的,在这种情况下,基于一个特性或一组特性的调度方法会更加复杂。

    这也意味着您需要实现 is_reference_wrapper_type 像这样:

    template <class T>
    struct is_reference_wrapper_type : mpi::false_ {};
    
    template <>
    struct is_reference_wrapper_type<std::vector<bool>::reference> : mpi::true_ {};
    
        4
  •  0
  •   Partial    15 年前

    使用特性或模板专门化将使其工作。