如何预防性病::载体的专业化(How to prevent specialization of st

2019-08-07 05:19发布

我有一个模板类具有类型的数据成员std::vector<T>其中T也是我的模板类的参数。

在我的模板类我有很长一段的逻辑,做这样的:

T &value = m_vector[index];

这似乎不是编译当T是一个布尔值,因为的std ::向量的[]操作不返回布尔参考,但是具有不同的类型。

一些替代品(虽然我不喜欢任何人):

  • 告诉我的用户,他们不能使用布尔作为模板参数
  • 有我的班布尔为专业化(但这需要一些代码重复)

难道没有办法告诉的std :: vector没有专门的布尔?

Answer 1:

你根本不可能有定期模板代码的行为进行T等于bool ,如果你的数据被表示为std::vector<bool> ,因为这不是一个容器。 正如@马克赎金指出的那样,你可以使用std::vector<char>代替,例如,通过这样的特质

template<typename T> struct vector_trait { typedef std::vector<T> type; };
template<> struct vector_trait<bool> { typedef std::vector<char> type; };

然后使用typename vector_trait<T>::type无论当前使用std::vector<T> 这里的缺点是,你需要使用强制类型转换,从charbool

在你自己的答案提出一个替代方案是写与隐式转换和构造器的包装

template<typename T>
class wrapper
{
public:
        wrapper() : value_(T()) {}
        /* explicit */ wrapper(T const& t): value_(t) {}
        /* explicit */ operator T() { return value_; }
private:
        T value_;
};

并使用std::vector< wrapper<bool> >到处而不必铸造。 然而,也有缺点,这是因为含有真实标准转换序列bool参数行为不同于与所述用户定义的转换wrapper<bool> (编译器可以至多使用1个用户定义的转换,并且尽可能多的标准转换为必要的) 。 这意味着,函数重载模板代码可以巧妙地打破。 你可以取消对explicit关键字,在上面的代码,但一遍介绍的详细程度。



Answer 2:

使用std::vector<char>代替。



Answer 3:

愿意为你下面的工作?

template <typename T>
struct anything_but_bool {
    typedef T type;
};

template <>
struct anything_but_bool<bool> {
    typedef char type;
};

template <typename T>
class your_class {
    std::vector<typename anything_but_bool<T>::type> member;
};

少轻率,名字anything_but_bool也许应该prevent_bool或相似。



Answer 4:

有防止一个方式vector<bool>专业化:传递一个自定义的分配器。

std::vector<bool, myallocator> realbool; 

下面的文章有一些细节: https://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=98

当然,这需要你有过控制vector的定义,所以它可能不是真正适合你的解决方案。 除此之外,它也有它自己的一些缺点...



Answer 5:

我发现一个更优雅的解决方案,根据您的所有投入。

首先,我定义了一个简单的类,拥有一个成员。 让我们把这种wrapperClass

template <typename T>
class wrapperClass
   {
   public:
      wrapperClass() {}
      wrapperClass(const T&value) : m_value(value) {}
      T m_value;
   };

现在我可以在这样的模板类定义我的std ::向量:

std::vector<wrapperClass<T>> m_internalVector;

由于sizeof(WrapperClass<bool>)也为1,我期望sizeof(WrapperClass<T>)将总是等于sizeof(T) 由于数据类型目前不是一个bool了,不进行专业化。

在地方,我现在得到的向量元素,我只需更换

m_internalVector[index]

通过

m_internalVector[index].m_value

但是,这似乎比使用性状的焦炭来代替布尔,然后使用强制转换为CHAR和布尔之间的转换更优雅(可能重新诠释转换到CHAR转换及到bool&)。

你怎么看?



Answer 6:

你可以使用一个自定义代理类来保存的bool。

class Bool
{
  public:
    Bool() = default;
    Bool(bool in) : value(in) {}

    Bool& operator=(bool in) {value = in;}
    operator bool() const& {return value;}

  private:
    bool value;
};

这可能需要一些调整你的目的,但它通常是我在这些情况下做的。



文章来源: How to prevent specialization of std::vector