条件编译和模板

Ale*_*ota 5 c++ templates

假设,我有一个代码:

template <typename T>
class C {
public:
    T f() { return m_result; }
    void todo() { m_result = doit<T>(); }
private:
    T m_result;
};
Run Code Online (Sandbox Code Playgroud)

如果Tvoid,我想回来void,一点也不m_result.
但是,编译器不允许实例化void类型.
其中一个决定是创建专业化.

template <> class C<void> { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

但我不支持几乎完全相同的代码.
我怎么不实例化m_result
我可以使用C++ 17.谢谢!

Oli*_*liv 4

您可以将数据放在基类中,然后使用if constexpr

template<class T>
struct C_data{
    T m_result;
    };
template<>
struct C_data<void>{
    };

template<class T>
class C: C_data<T>
  {
  static constexpr auto is_void = std::is_same_v<T,void>;
  public:
  auto f(){
     if constexpr(is_void)
        return this->m_result;
     else
        return;
     }
  void todo(){
     if constexpr(is_void)
       this->m_result = doit<T>();
     else
        doit<T>();
     }
   };
Run Code Online (Sandbox Code Playgroud)

但可以说 C 类的专门化更清晰,因为模板类的所有成员都应该依赖于所有模板参数(否则您应该拆分您的类以避免代码膨胀)。

因此,我更愿意完全专门化 C,并使 C 类的一部分独立于 T(C 的基类):

class C_base{
    //any thing that is independent of T;
    };
template<class T>
class C: public C_base{
    //any thing that depend on T
    };
template<>
class C<void>: public C_base{
    //any thing that depend on T;
    };
Run Code Online (Sandbox Code Playgroud)

您还可以按成员函数专门化成员函数,但我发现它不太干净。

您将在几乎所有标准库实现的标头中找到最后一个代码结构。