【问题标题】:Using C++ templates to switch algorithms使用 C++ 模板切换算法
【发布时间】:2020-05-10 17:17:55
【问题描述】:

我有一个具有pointQuery 函数的C++ 类。目前,当我必须在线性搜索和二进制搜索之间切换时,我会注释代码的另一部分。我看到了this 的帖子,并试图重构我的代码。我的代码如下:

namespace searchStrategy{
    struct linearSearch{};    
    struct binarySearch{};
}

template<typename T, typename LookupStrategy> class leaf:public rtNode<T>{
    public:T points[maxCapLeaf][d]; // search to be done on this array
    // some other class members, most of which used in the search

    template<typename searchStrategy::linearSearch> bool pointQuery(const T* f) const{
        // some code
    }

    template<typename searchStrategy::binarySearch> bool pointQuery(const T* f) const{
        // some code
    }

};

类的对象被创建为:

leaf<T, LookupStrategy>* temp = new leaf<T, LookupStrategy>(some_input_params);

其中LookupStrategysearchStrategy::binarySearchsearchStrategy::linearSearch

当我编译它时,我得到以下错误:

/file_address/template.cpp:164:39: error: non-type template parameters of class type only available with ‘-std=c++2a’ or ‘-std=gnu++2a’
  164 |     template<typename searchStrategy::linearSearch> bool pointQuery(const T* f) const{
      |                                       ^~~~~~~~~~~~
/file_address/template.cpp:200:39: error: non-type template parameters of class type only available with ‘-std=c++2a’ or ‘-std=gnu++2a’
  200 |     template<typename searchStrategy::binarySearch> bool pointQuery(const T* f) const{
      |                                       ^~~~~~~~~~~~
/file_address/template.cpp:200:58: error: ‘template<class T, class LookupStrategy> template<<typeprefixerror><anonymous> > bool leaf<T, LookupStrategy>::pointQuery(const T*) const’ cannot be overloaded with ‘template<class T, class LookupStrategy> template<<typeprefixerror><anonymous> > bool leaf<T, LookupStrategy>::pointQuery(const T*) const’
  200 |     template<typename searchStrategy::binarySearch> bool pointQuery(const T* f) const{
      |                                                          ^~~~~~~~~~
/file_address/template.cpp:164:58: note: previous declaration ‘template<class T, class LookupStrategy> template<<typeprefixerror><anonymous> > bool leaf<T, LookupStrategy>::pointQuery(const T*) const’
  164 |     template<typename searchStrategy::linearSearch> bool pointQuery(const T* f) const{
      |

谁能解释一下我做错了什么,我该如何解决这个问题? (请注意,函数需要保留在类本身中,我无法将其转移到命名空间,因为在搜索函数中使用了很多类成员)谢谢...

【问题讨论】:

    标签: c++ class templates


    【解决方案1】:
    namespace searchStrategy {
        struct linearSearch{};    
        struct binarySearch{};
    }
    
    template<typename T, typename LookupStrategy> class leaf: public rtNode<T> {
      private:
        // Overload 1
        bool pointQuery(const T* f, linearSearch) const {
            // some code
        }
    
        // Overload 2
        bool pointQuery(const T* f, binarySearch) const {
            // some code
        }
    
      public:
        T points[maxCapLeaf][d];
    
        bool pointQuery(const T* f) const {
            return pointQuery(points, LookupStrategy{});
        }
    };
    

    【讨论】:

    • 感谢您的建议。我完全按照你说的做了,并且编辑了我的帖子。你能看一下吗?
    【解决方案2】:

    (部分)特化可能是一种解决方案,但成员/函数不能部分特化,您可以对整个类进行部分特化。

    作为替代方案,

    在 C++17 中,您可以使用 if constexpr:

    bool pointQuery(const T* f) const
    {
        if constexpr (std::is_same_v<LookupStrategy, searchStrategy::linearSearch>)
            // some code
        } else { // searchStrategy::binarySearch
            // some code
        }
    }
    

    在 C++20 中,requires:

    bool pointQuery(const T* f) const
    requires(std::is_same_v<LookupStrategy, searchStrategy::linearSearch>)
    {
        // some code
    }
    
    bool pointQuery(const T* f) const
    requires(std::is_same_v<LookupStrategy, searchStrategy::binarySearch>)
    {
        // some code
    }
    

    在以前的标准中,您可能会使用标签调度:

    private:
    bool pointQuery(searchStrategy::linearSearch, const T* f) const
    {
        // some code
    }
    
    bool pointQuery(searchStrategy::binarySearch, const T* f) const
    {
        // some code
    }
    public:
    bool pointQuery(const T* f) const
    {
        return pointQuery(LookupStrategy{}, f);
    }
    

    【讨论】:

    • 我不愿意使用 if-else 认为它们可能会降低性能。是正确的还是完全不影响性能?
    • if constexpr 在编译时完成,因此没有运行时开销。 (对于常规的if,编译器可能会轻松优化,但实际上没有保证)。
    • 所以C++17解决方案只会增加编译时间,而NOT运行时间?
    • 对于运行时,没有开销(仅存在正确的块)。对于编译时间,不确定哪些替代方案的成本最高或最低。我会说等价。
    • 编译时间不是问题。谢谢你:)
    猜你喜欢
    • 2015-03-10
    • 1970-01-01
    • 1970-01-01
    • 2019-02-24
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    • 2010-11-26
    • 1970-01-01
    相关资源
    最近更新 更多