提问者:小点点

C++条件模板构造函数


我有一个handleid类,它的操作类似于智能指针。以下是重要的比特:

template<class T>
class HandleID
{
// Only if T is not const
friend class HandleID<const T>;

public:
    HandleID();
    HandleID(int id);
    HandleID(const HandleID<T>& other);
    HandleID& operator=(const HandleID<T>& other);

    // Only if T is const
    HandleID(const HandleID<const removed T>& other);
    HandleID& operator=(const HandleID<const removed T>& other);


private:
    T* cachedPointer;
    int id;
};

现在,我希望能够从handleid构造handleid,而不是相反。复制赋值运算符也是这样:handleid=handleid应该合法,但handleid=handleid不应该合法。

现在,我想添加一个模板,专门化或其他东西,但我肯定有一个更好的方法来做这件事。请注意,非常量版本必须将常量版本添加为友元,才能访问constructor/assignmnent运算符中的私有成员。


共1个答案

匿名用户

斯菲纳伊的方式...

为了简化,可以为no-constt添加using类型

using no_const_T = std::remove_const_t<T>;

t不是常量时,这等于t;当t常量时,则不同。

那么只有当tno_const_t不同时,SFINAE才能启用构造函数/运算符

template <typename U = T,
          std::enable_if_t<not std::is_same_v<U, no_const_T>, int> = 0>
HandleID(const HandleID<no_const_T> & other);

template <int..., typename U = T, 
          std::enable_if_t<not std::is_same_v<U, no_const_T>, int> = 0>
HandleID& operator=(const HandleID<no_const_T>& other);

注意,您必须检查t是否与no_const_t相等或不同,而不是直接使用t而是使用t初始化的本地(方法的)模板参数(u)。

--编辑--

OP询问

当我想要分离声明(您提供的那个)和实现(例如,在文件中更低的类之外)时,语法是什么

是精神错乱。

下面是一个在类主体外部实现的支持SFINAE的方法的完整编译(愚蠢的)示例。

#include <type_traits>

template <typename T>
class HandleID
 {
   friend class HandleID<T const>;

   using no_const_T = std::remove_const_t<T>;

   public:
      HandleID () {}
      HandleID (int) {}
      HandleID (HandleID<T> const &) {}

      template <typename U = T,
                std::enable_if_t<not std::is_same_v<U, no_const_T>, int> = 0>
      HandleID (HandleID<no_const_T> const &);

      HandleID & operator= (HandleID<T> &)
       { return *this; }

      template <int..., typename U = T,
                std::enable_if_t<not std::is_same_v<U, no_const_T>, int> = 0>
      HandleID & operator= (HandleID<no_const_T> const &);
 };

template <typename T>
template <typename U,
          std::enable_if_t<not std::is_same_v<U,
             std::remove_const_t<T>>, int>>
HandleID<T>::HandleID (HandleID<std::remove_const_t<T>> const &)
 { }

template <typename T>
template <int..., typename U,
          std::enable_if_t<not std::is_same_v<U,
             std::remove_const_t<T>>, int>>
HandleID<T> & HandleID<T>::operator=
   (HandleID<std::remove_const_t<T>> const &)
 { return *this; }

int main()
 {
   HandleID<int>       id0;
   HandleID<int const> idc0;

   HandleID<int>  id1{id0};  // copy constructor: compile
   //HandleID<int>  id2{idc0}; // constructor disabled: compilatrion error

   HandleID<int const>  idc1{idc0};  // copy constructor: compile
   HandleID<int const>  idc2{id0};   // constructor enabled: compile
 }

相关问题


MySQL Query : SELECT * FROM v9_ask_question WHERE 1=1 AND question regexp '(c++|条件|模板|构造|函数)' ORDER BY qid DESC LIMIT 20
MySQL Error : Got error 'repetition-operator operand invalid' from regexp
MySQL Errno : 1139
Message : Got error 'repetition-operator operand invalid' from regexp
Need Help?