C++ 覆盖嵌套类只能部分说服编译器

标签 c++ templates inheritance c++11 nested-class

前言

下面有一个 SSCCE 链接。

我已经定义了一个模板类,它在我的程序中声明了一个嵌套类。该模板适用于许多不同的数据类型(即那些被 std::ostream::operator << 重载的数据类型。我现在想将此模板与一个不能使用它的类型一起使用,因为该类型在 std::ostream::operator << 中没有被重载。我不想添加另一个重载方法。

这是基本界面:

class Value;

class Datatype {

public:

    virtual std::string to_string(Value* value) = 0;

};

class Value {

    Datatype* m_type;

public:

    Value(Datatype* type) : m_type(type) { }

    std::string to_string() {
        return m_type->to_string(this);
    }

};

什么 WrapValueImpl模板类确实(见下文),是传递一个ValueDatatype一站式实现。

template <typename T>
class WrapValueImpl : public Value {

    T m_val;

public:

    WrapValueImpl(Datatype* type) : Value(type) { }

    T& get() {
        return m_val;
    }

    static T& get(Value* value) {
        return static_cast<WrapValueImpl*>(value)->get();
    }

    static void set(Value* value, const T& other) {
        get(value) = other;
    }

    class Type : public ::Datatype {

    public:

        virtual std::string to_string(Value* value) {
            std::ostringstream stream;
            stream << WrapValueImpl::get(value);
            return stream.str();
        }

    };

};

示例用法:

typedef WrapValueImpl<int> IntValue;

int main() {
    IntValue::Type t;
    IntValue v(&t);
    IntValue::set(&v, 42);

    std::cout << v.to_string() << "\n"; // prints 42
    return 0;
}

到目前为止一切正常,这正是我想要的。

问题

但是现在,我想使用 WrapValueImpl类型名称在 std::ostream::operator << 中不受支持.请再次注意,我不想添加对 << 的支持。运营商。

更确切地说,我想覆盖 Type WrapValueImpl 中的类实现正确的字符串转换。

typedef std::vector<Value*> ValueArray;
class ArrayValue : public WrapValueImpl<ValueArray> {

public:

    ArrayValue(Datatype* type) : WrapValueImpl<ValueArray>(type) { }

    class Type : public WrapValueImpl<ValueArray>::Type {

    public:

        virtual std::string to_string(Value* value) {
            std::ostringstream stream;
            stream << "[";

            ValueArray& array = ArrayValue::get(value);
            ValueArray::const_iterator it = array.begin();
            for (; it != array.end(); it++) {
                stream << (*it)->to_string() << ", ";   
            }
            stream << "]";
            return stream.str();
        }

    };

};

但它根本无法编译。编译器产生错误,就好像我使用的是原始的 WrapValueImpl<ValueArray>::Type类而不是 ArrayValue::Type类(class)。然而,我确实进行了测试并在 Type::to_string() 中插入了打印件。并调用正确的方法(被覆盖类的方法)。

(SSCCE) 但它实际上使用了正确的 Type类...

在 Coliru 上的以下片段中,您可以找到我正在谈论的内容的完整工作示例。您可以切换 USE_ARRAY宏查看使用 ArrayValue 的结果类。

http://coliru.stacked-crooked.com/a/820e2f2550a8363e

在这个例子中,我还证明了编译器实际上选择了正确的嵌套类型类,但它提示原始实现。当它实际上不使用该类型时,为什么会麻烦?

最佳答案

问题是当你定义TypeArrayValue像这样public WrapValueImpl<ValueArray>::Type然后编译器将实例化 Type来自 WrapValueImpl暗示。 TypeWrapValueImpl 中定义在模板化类型 T 上使用运算符 <<,因为 T 没有运算符 <<,所以会抛出错误。

解决此问题的一种方法是为您的值类型使用运算符:

std::ostringstream& operator << (std::ostringstream& stream,const ValueArray & va);

class ArrayValue : public WrapValueImpl<ValueArray> {

public:

    ArrayValue(Datatype* type) : WrapValueImpl<ValueArray>(type) { }

};

std::ostringstream& operator << (std::ostringstream& stream,const ValueArray & array)
{
    stream << "[";

    ValueArray::const_iterator it = array.begin();
    for (; it != array.end(); it++) {
        stream << (*it)->to_string() << ", ";   
    }
    stream << "]";
    return stream;
};

只是不要定义 Type在你的ArrayValue类。

关于C++ 覆盖嵌套类只能部分说服编译器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19772163/

相关文章:

c++ - 多重继承和虚拟继承 C++

c++ - 函数指针作为模板参数,类型推导失败

c# - 从其通用父类继承的嵌套类

c++ - 如何解决 C++ 的代码片段 cin.getline 的运行时跳过

java - 关于Java中父类(super class)变量引用子类对象

c++ - gcc ld : method to determine link order of static libraries

c++ - 如果析构函数有副作用并且对象是从另一个静态对象的析构函数访问的,如何进行静态反初始化?

c++ - 更改 CMFCRibbonStatusBar 的文本,但显示第一个字符和三个点(如 "C...")

c++ - 为什么不能推导嵌套在模板类中的枚举的模板参数?

C++11 - 检测运算符 new[] 的方法