【问题标题】:How to avoid code duplicates with class template specializations如何使用类模板特化避免代码重复
【发布时间】:2020-12-30 05:39:08
【问题描述】:

我想避免下面代码中的重复。

#include <iostream>

struct Bar{};

template <class... Args>
struct FooClass;

template <class... Args>
inline void foo(Args&&... args) {
  FooClass<Args...>::impl(std::forward<Args>(args)...);
}

// Duplicate 1.
// Const ref version
template <>
struct FooClass<Bar const&> {
  inline static void impl(const Bar& b) {
    std::cout << "dup1" << std::endl;
  }
};

// Duplicate 2.
// Copy version
template <>
struct FooClass<Bar> {
  inline static void impl(const Bar& b) {
    std::cout << "dup2" << std::endl;
  }
};

// Duplicate 3.
// Non-const ref version
template <>
struct FooClass<Bar&> {
  inline static void impl(const Bar& b) {
    std::cout << "dup3" << std::endl;
  }
};

int main()
{
  const Bar b2;
  foo(b2);  
  foo(Bar{});
  Bar b;
  foo(b);
}

我很确定这可以通过某种方式使用 enable_if 和通用引用,但我想不通。

顺便说一句,这个程序输出:

dup1
dup2
dup3

如果三个特化中的任何一个被注释掉,它将不会编译。

【问题讨论】:

    标签: c++ templates c++14 variadic-templates


    【解决方案1】:

    为什么不直接从模板参数中去掉const&amp;

    template<class... Args>
    void foo(Args&&... args) {
        FooClass<std::decay_t<Args>...>::impl(std::forward<Args>(args)...);
        //       ^^^^^^^^^^^^
    }
    
    template<>
    struct FooClass<Bar> {
        static void impl(const Bar&) {
            std::cout << "bar" << std::endl;
        }
    };
    
    int main() {
        const Bar b2;
        foo(b2);       // prints "bar"
        foo(Bar{});    // prints "bar"
        Bar b;
        foo(b);        // prints "bar"
    }
    
    

    Demo

    【讨论】:

    • 函数FooClass::impl可以接受通用引用吗?
    • @jignatius,当然。只需将其作为模板本身即可。
    • 可能类似于this?
    • @jignatius 可以有不同的解决方案。这个问题对于“避免”的确切含义是模糊的,并且 OP 对所有参数使用const&amp;。这就是为什么我决定保持原样。
    • @Evg 这看起来很棒!正是我的意图。 impl 函数旨在采用 const ref;我只是在寻找一种方法来避免三个不同专业之间的代码重复。
    【解决方案2】:

    由于您将参数完美地转发给impl,据我所知,您将需要拥有所有重复项,因为编译器必须完全匹配专业化的类型。

    一个简单的解决方法是复制所有内容:

    #include <iostream>
    
    struct Bar{};
    
    template <class... Args>
    struct FooClass;
    
    template <class... Args>
    inline void foo(Args... args) {
      FooClass<Args...>::impl(args...);
    }
    
    // Duplicate 1.
    // Const ref version
    template <>
    struct FooClass<Bar> {
      inline static void impl(const Bar& b) {
        std::cout << "dup1" << std::endl;
      }
    };
    
    int main()
    {
      const Bar b2;
      foo(b2);  
      foo(Bar{});
      Bar b;
      foo(b);
    }
    

    这在 Clang 12.0.0 中编译得很好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-29
      相关资源
      最近更新 更多