【问题标题】:C++11: Specialize/restrict method on depending on a container's value_typeC++11:根据容器的 value_type 专门化/限制方法
【发布时间】:2013-05-08 03:51:31
【问题描述】:

我有一个模板action 方法,它接受任何类型的STL 容器C。但是,包含的项目 (C::value_type) 必须是 ClassAClassB。到目前为止一切顺利:

struct Whatever {
    template<typename C>
    void action(const C& c) {
        static_assert(std::is_same<typename C::value_type, ClassA>::value ||
                      std::is_same<typename C::value_type, ClassB>::value,
                      "Wrong C::value_type");
        // do something with c
    }
};

// Usage:
Whatever w;
w.action(std::vector<ClassA>{1, 2, 3});
w.action(std::unordered_set<ClassB>{1, 2, 3});

注意:封闭类不是模板,唯一的模板就是action方法。

现在,根据C::value_type,我想专门研究该方法的行为。你猜对了,这就是我的大脑开始融化的地方。


我相信 SFINAE 是要走的路,但显然我太生疏了,无法让它正常工作:几个小时后,大量的助手 structs 和太多的咖啡对我自己的健康不利,编译器只是不停地对我大喊通常的 500 多个模板错误。复制我的助手structs 或这里的错误毫无意义,这几乎是无用的垃圾。

但是,我不得不承认,自从十年来我并没有真正接触过所有的 C++ 模板 (r) 演进(甚至使用 SFINAE),所以难怪我失败得这么厉害。

我强烈怀疑 C++11 现在有简单、易于使用的类似 SFINAE 的工具来实现我想要的,但我什至不知道从哪里开始在文档中搜索。搜索引擎也无济于事,一次太多的新信息让我无法理解与我的问题相关/不相关的内容。

由于我完全不知所措,所以我只是采取婴儿步骤并问...我的问题有两个:

  • 如何使用现代 C++11 模板工具根据 C::value_type 的实际类型专门化方法的行为?
  • (可选)是否有标准方法来检查 C 是否真的是一个容器?

感谢您的关注。

【问题讨论】:

    标签: c++ c++11 sfinae specialization


    【解决方案1】:

    我想知道你为什么不这样做:

     template<typename C>
     void action(const C& c) 
     {
            static_assert(std::is_same<typename C::value_type, ClassA>::value ||
                          std::is_same<typename C::value_type, ClassB>::value,
                          "Wrong C::value_type");
    
          action_worker(c, static_cast<typename C::value_type*>(0));
     }
    
    private:
    
     template<typename C>
     void action_worker(const C& c, ClassA *) 
     {
         //specialized code when C::value_type is ClassA
     }
    
     template<typename C>
     void action_worker(const C& c, ClassB *) 
     {
         //specialized code when C::value_type is ClassB
     }
    

    现在取决于C::value_typeaction_worker 的第二个参数可以是ClassA*ClassB*。这将使编译器能够在您编写专用代码的地方选择正确的重载。

    对于您问题的第二部分,请参阅此答案中is_container 类模板的实现:

    希望对您有所帮助。

    【讨论】:

    • 哦,天哪,我真傻……我应该考虑过这一点,但我正在寻找可能永远不会有的相反方向。 O_o 非常感谢!这绝对是对我问题第一部分的一个很好的回答,非常直截了当。
    • @syam:查看编辑。它链接到您问题第二部分的解决方案。
    • 再次感谢,您成功了。希望我能再次投票给你。 ;)
    【解决方案2】:

    由于您只支持这两种类型,我会考虑使用 enable_if:

    struct Whatever
    {
        template<typename C>
        typename std::enable_if<std::is_same<typename C::value_type, ClassA>::value, void>::type
        action(const C& c)
        {
            std::cout << "ClassA\n";
        }
    
        template<typename C>
        typename std::enable_if<std::is_same<typename C::value_type, ClassB>::value, void>::type
        action(const C& c)
        {
            std::cout << "ClassB\n";
        }
    };
    

    【讨论】:

    • 确实是我最初追求的那种东西。谢谢,现在我有地方可以开始研究这些新功能了... :)
    猜你喜欢
    • 2013-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多