Intellisense认为我的符号含糊不清

时间:2015-01-16 09:15:05

标签: c++ visual-studio visual-c++ enums visual-studio-2015

我正在https://bitbucket.org/chopsii/typesafe-enums

编写自己的类型安全枚举头文件库

这个想法是替换非类型安全的c风格的枚举,如:

enum ItemCategory
{
    BLOCK,
    WEAPON
};

使用适当类型安全的东西。

到目前为止,我的解决方案使用了一个宏,对于一个与上面的枚举相当的示例,它看起来像这样:

TypesafeEnum(ItemCategory,
    (BLOCK)
    (WEAPON)
);

并扩展为看起来像这样的东西:

template<typename InnerType>
class Wrapped {
public:
    InnerType getValue() const { return _val; }

    bool operator<(const Wrapped<InnerType>& rhs) const { ; return _val < rhs._val; }
    bool operator>(const Wrapped<InnerType>& rhs) const { ; return _val > rhs._val; }

    bool operator==(const Wrapped<InnerType>& rhs) const { ; return _val == rhs._val; }


private:
    InnerType _val;
protected:

    explicit Wrapped<InnerType>(const InnerType& val) : _val(val) {}
    void setValue(const InnerType& val) { _val = val; }
};

class WrappedTypeItemCategory : private Wrapped<int>
{
private:
    typedef const std::string* strptr;
    typedef const std::string* const cstrptr;
    explicit WrappedTypeItemCategory(const std::string& label, int val): Wrapped<int>(val), str(&label)
    {}
    cstrptr str;
public:
    static WrappedTypeItemCategory make(const std::string& label, int val)
    {
        return WrappedTypeItemCategory(label, val);
    }
    void operator=(const WrappedTypeItemCategory& rhs)
    {
        ;
        setValue(rhs.getValue());
        const_cast<strptr>(str) = rhs.str;
    }
    int getValue() const
    {
        return Wrapped<int>::getValue();
    }
    const std::string& getString() const
    {
        return *str;
    }
    bool operator<(const WrappedTypeItemCategory & rhs) const
    {
        ;
        return getValue() < rhs.getValue();
    }
    bool operator>(const WrappedTypeItemCategory & rhs) const
    {
        ;
        return getValue() > rhs.getValue();
    }
    bool operator==(const WrappedTypeItemCategory & rhs) const
    {
        ;
        return getValue() == rhs.getValue();
    }
    friend std::ostream & operator<<(std::ostream &os, const WrappedTypeItemCategory& rhs)
    {
        ;
        return os << *rhs.str << "(" << rhs.getValue() << ")";
    }
};
;
namespace {
    template<typename T> class ItemCategoryInner : public TypesafeEnumBase
    {
    public:
        static const WrappedTypeItemCategory BLOCK;
        static const WrappedTypeItemCategory WEAPON;
        static const std::string BLOCKStr;
        static const std::string WEAPONStr;
    };
    template<typename T> const WrappedTypeItemCategory ItemCategoryInner<T>::BLOCK = WrappedTypeItemCategory::make(ItemCategoryInner<T>::BLOCKStr, 0);
    template<typename T> const WrappedTypeItemCategory ItemCategoryInner<T>::WEAPON = WrappedTypeItemCategory::make(ItemCategoryInner<T>::WEAPONStr, 1);
    template<typename T> const std::string ItemCategoryInner<T>::BLOCKStr("ItemCategory::BLOCK");
    template<typename T> const std::string ItemCategoryInner<T>::WEAPONStr("ItemCategory::WEAPON");
    struct ItemCategoryTemplateConstantTrick
    {};
};
class ItemCategory : public ItemCategoryInner<ItemCategoryTemplateConstantTrick>
{
private:
    const WrappedTypeItemCategory* const val;
public:
    class InvalidValueError : public std::runtime_error
    {
    public:
        const int val;
        InvalidValueError(int val): std::runtime_error(std::string("Invalid value given for ") + "ItemCategory::make"), val(val)
        {}
    };
    ItemCategory(const WrappedTypeItemCategory& value): val(&value)
    {}
    void operator=(const ItemCategory& rhs)
    {
        const_cast<const WrappedTypeItemCategory*>(val) = rhs.val;
    }
    static ItemCategory make(const int& val)
    {
        if (val == ItemCategory::BLOCK.getValue()) return ItemCategory(ItemCategory::BLOCK);
        if (val == ItemCategory::WEAPON.getValue()) return ItemCategory(ItemCategory::WEAPON);
        ;
        throw InvalidValueError(val);
    }
    const WrappedTypeItemCategory* const getWrappedValue() const
    {
        return val;
    }
    int getValue() const
    {
        return val->getValue();
    }
    const std::string & getString() const
    {
        return val->getString();
    }
    bool operator<(const ItemCategory& rhs) const
    {
        return *val < *rhs.val;
    }
    bool operator>(const ItemCategory& rhs) const
    {
        return *val > *rhs.val;
    }
    bool operator==(const WrappedTypeItemCategory& rhs) const
    {
        return *val == rhs;
    }
    bool operator!=(const WrappedTypeItemCategory& rhs) const
    {
        return !(*val == rhs);
    }
    bool operator<=(const WrappedTypeItemCategory& rhs) const
    {
        return (*val == rhs || *val < rhs);
    }
    bool operator>=(const WrappedTypeItemCategory& rhs) const
    {
        return (*val == rhs || *val > rhs);
    }
    void print(std::ostream& os) const override
    {
        os << *val;
    }
    friend std::ostream & operator<<(std::ostream &os, const ItemCategory& rhs)
    {
        rhs.print(os);
        return os;
    }
};
;

如果我手动预扩展它,就像我在这里做的那样 - 通过预编译到文件 - 然后intellisense处理它直到所说的行:

class ItemCategory : public ItemCategoryInner<ItemCategoryTemplateConstantTrick>

此时它开始认为ItemCategoryInnerItemCategoryTemplateConstantTrick不明确,以及文件的每几行都有许多其他内容。

包含此代码的标头包含在许多地方。我知道我违反了One Definition规则,这就是为什么我使用模板常量技巧,但我认为我需要违反ODR,因为我的目标是为C ++枚举提供一个易于使用的基于宏的类型安全替换。

我不确定是否违反ODR是导致我的问题或其他原因。我尝试了__declspec(selectany),但它似乎没有帮助 - 我更希望这个宏最终是跨平台的,因为如果它成功了,我还有其他项目我会用它。

无论哪种方式,使用枚举的.cpp文件等都可以,并且智能感知正确地建议选项。

然而,在一个可能相关的说明中,如果我不预先扩展宏,智能感知不能解析它,它根本不知道ItemCategory是什么,即使它编译并正常工作。

我只是希望我的intellisense能够与我的类型安全枚举一起正常工作 - 它会减慢智能感知并将其混淆在同一项目中的其他代码中。

0 个答案:

没有答案