15

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

在我的模板类中,我有很多这样做的逻辑:

T &value = m_vector[index];

当 T 是布尔值时,这似乎无法编译,因为 std::vector 的 [] 运算符不返回布尔引用,而是返回不同的类型。

一些替代品(尽管我不喜欢其中任何一个):

  • 告诉我的用户他们不能使用 bool 作为模板参数
  • 对我的类有专门的 bool (但这需要一些代码重复)

有没有办法告诉 std::vector 不要专门用于 bool?

4

6 回答 6

10

如果您的数据由 表示,则T您根本无法让模板化代码定期运行,因为这不是容器。正如@Mark Ransom 所指出的,您可以改用,例如通过这样的特征boolstd::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上面代码中的关键字,但这会再次引入冗长。

于 2013-01-17T20:54:20.987 回答
4

改为使用std::vector<char>

于 2013-01-17T20:58:59.687 回答
4

以下内容对您有用吗?

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或相似的。

于 2013-01-17T21:05:36.190 回答
1

根据您的所有输入,我找到了一个更优雅的解决方案。

首先,我定义了一个包含一个成员的简单类。让我们称之为wrapperClass

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

现在我可以像这样在我的模板类中定义我的 std::vector :

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

由于sizeof(WrapperClass<bool>)也是 1,我希望它sizeof(WrapperClass<T>)总是等于sizeof(T)。由于数据类型现在不再是 bool,因此不执行特化。

在我现在从向量中获取元素的地方,我只需替换

m_internalVector[index]

经过

m_internalVector[index].m_value

但这似乎比使用特征将 bool 替换为 char,然后使用强制转换在 char 和 bool 之间进行转换(并且可能重新解释强制转换以将 char& 转换为 bool&)要优雅得多。

你怎么看?

于 2013-01-18T10:48:11.647 回答
1

您可以使用自定义代理类来保存布尔值。

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

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

  private:
    bool value;
};

这可能需要根据您的目的进行一些调整,但在这些情况下我通常会这样做。

于 2013-01-17T21:07:01.923 回答
0

有一种方法可以防止vector<bool>专业化:传递自定义分配器。

std::vector<bool, myallocator> realbool; 

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

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

于 2013-01-17T21:02:54.320 回答