避免void指针 [英] Avoiding void pointers

查看:280
本文介绍了避免void指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在C ++ 11中实现自己的编程语言。

I am implementing my own programming language in C++11.

我设计的数据类型之一是 Token 类。它用于存储从源文件读取的令牌,令牌的内容,类型以及遇到的行。

One of the datatypes I've designed is the Token class. It is meant to store a token read from the source file, with the content of the token, it's type, and the line at which it was encountered.

令牌可以可以是单字符符号,长字符串,数字或名称。因此,它需要能够存储不同的数据类型,例如符号的字符,数字的double,以及名称和字符串的std :: string。

A token can be either a single-character symbol, a lenghtful string, a number, or a name. So it needs to be able to store different data types, either a character for symbols, a double for numbers, and a std::string for names and strings.

方法我实现这是通过将值存储在一个void指针,并通过添加一个属性的custome枚举,有助于了解应该使用什么类型的void指针。

The way I'm implementing this is by storing that value in a void pointer, and by adding an attribute of a custome enum which helps understand what type should you cast that void pointer to.

当然,我可以为Token的每个子类型设置一个类,但是我会在某个时候需要将它们全部存储为 Token * 意味着我仍然需要一个枚举,帮助我知道我应该把令牌* 类型转换为

Of course I could have a class for each of those subtypes of Token, but I would at some point anyway need to store all of them as a Token*, which means I will still need to have an enum which helps me know what type should I cast that Token* to.

这里是它的实际代码:

enum token_type {
    symbol,
    number,
    name,
    string
};

struct Token {
    void* value = nullptr;
    token_type type;
    unsigned int line;

    Token(void* new_value, token_type new_type, unsigned int new_line):
        value(new_value), type(new_type), line(new_line)
        {}

    ~Token() {
        switch (type) {
            case symbol:
                delete (char*) value;
                break;
            case number:
                delete (double*) value;
                break;
            case name:
            case string:
                delete (std::string*) value;
        }
    }
};

什么是一个好的设计模式来实现,避免使用void指针和?每个人都在告诉我这个设计是错误的,但是我没有建议如何改善这种情况,所以我在这里问。

What is a good design pattern to implement this which avoids the use of void pointers and (possibly) enums? Everyone keeps telling me that this design is wrong, but I got no suggestions on how to actually improve this situation, so I asked here.

推荐答案

您可以删除类型如下:

class Token {
    using Deleter = void(void*);
    using Func = void(*)(void*);

    template<typename T>
    static void proto(void *ptr) {
        T t = static_cast<T*>(ptr);
        // do whatever you want here...
        // ... or use specializations.
    }

public:
    template<typename T>
    Token(T* value):
        value{value, [](void *ptr) { delete static_cast<T*>(ptr); }},
        func{&proto<T>}
    {}

    void operator()() {
        func(value.get());
    }

private:
    std::unique_ptr<void, Deleter> value;
    Func func;
};

实例将被智能指针知道的类型正确删除。

以类似的方式,通过 proto 的一系列特化,您可以为要处理的多个类型定义不同的操作。

The instance will be correctly deleted for the smart pointer knows the type.
In a similar manner, by means of a bunch of specializations of proto, you can define different operations for the multiple types you want to deal with.

它遵循一个最小的工作示例:

It follows a minimal, working example:

#include <memory>
#include <iostream>

struct A {};
struct B {};

class Token {
    using Deleter = void(*)(void*);
    using Func = void(*)(void*);

    template<typename T>
    static void proto(void *ptr);

public:
    template<typename T>
    Token(T *value): 
        value{value, [](void *ptr) { delete static_cast<T*>(ptr); }},
        func{&proto<T>}
    {}

    void operator()() {
        func(value.get());
    }

private:
    std::unique_ptr<void, Deleter> value;
    Func func;
};

template<>
void Token::proto<A>(void *ptr) {
    A *a = static_cast<A*>(ptr);
    // use a
    (void)a;
    std::cout << "A" << std::endl;
}

template<>
void Token::proto<B>(void *ptr) {
    B *b = static_cast<B*>(ptr);
    // use b
    (void)b;
    std::cout << "B" << std::endl;
}

int main() {
    Token token{new A};
    token();
}

这篇关于避免void指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆