我可以从最终用户隐藏此概念的实现详细信息吗?

发布于 2025-02-13 06:04:49 字数 1447 浏览 0 评论 0原文

我已经看过几个类似的问题。也许我不是在那里解决解决方案。在这些问题中,当返回类型为auto或模板时,然后将声明和定义分为两个不同单位会导致编译失败。可以通过明确声明该功能定义的具体签名来解决这。就我而言,我不确定该怎么做。

我的情况如下:

// api.h
template <typename TImpl>
concept IsAProcessor = requires(TImpl impl)
{
    impl.init();
    impl.process();
    impl.deinit();
};


enum UseCase {
    USECASE1,
    USECASE2
};

template <IsAProcessor TImpl>
void Process(TImpl& impl)
{
    impl.process();
}

class Engine
{
public:
    IsAProcessor auto getInstance(UseCase a);
};
// End - api.h

// api.cpp
#include "api.h"
#include "third_party.h"
IsAProcessor auto Engine::getInstance(UseCase a) {
    switch (UseCase) {
        case USECASE1:
            return UseCase1Impl(); // Defined in third_party.h and satisfies concept requirement.
        case USECASE2:
            return UseCase2Impl();
    }

    
}
// End - api.cpp

// third_party.h
class UseCase1Impl {
public:
    void init(void);
    void process(void);
    void deinit(void);
}
// End - third_party.h

// third_party.cpp
#include "third_party.h"
void UseCase1Impl::init(void) {...};
// and so forth
// End - third_party.cpp

// User code
#include "api.h"

{
    auto en = Engine();
    auto usecase = en.getInstance(UseCase::USECASE1);
    //^^^ cannot be used before it is defined here    
    Process(usecase);
}

正如我在问题中提到的那样,揭露Usecase1impl和usecase2impl并不希望。我如何克服错误:函数'getInstance'使用推论返回类型不能在定义之前使用>

I have looked at several similar questions on SO. Maybe I am not grokking the solutions there. In those questions when the return type is auto or templated then separating declaration and definition in two different units causes a failure in compilation. This can be solved by explicitly declaring a concrete signature for the function definition. In my case I am not sure how to do that.

My scenario is as below:

// api.h
template <typename TImpl>
concept IsAProcessor = requires(TImpl impl)
{
    impl.init();
    impl.process();
    impl.deinit();
};


enum UseCase {
    USECASE1,
    USECASE2
};

template <IsAProcessor TImpl>
void Process(TImpl& impl)
{
    impl.process();
}

class Engine
{
public:
    IsAProcessor auto getInstance(UseCase a);
};
// End - api.h

// api.cpp
#include "api.h"
#include "third_party.h"
IsAProcessor auto Engine::getInstance(UseCase a) {
    switch (UseCase) {
        case USECASE1:
            return UseCase1Impl(); // Defined in third_party.h and satisfies concept requirement.
        case USECASE2:
            return UseCase2Impl();
    }

    
}
// End - api.cpp

// third_party.h
class UseCase1Impl {
public:
    void init(void);
    void process(void);
    void deinit(void);
}
// End - third_party.h

// third_party.cpp
#include "third_party.h"
void UseCase1Impl::init(void) {...};
// and so forth
// End - third_party.cpp

// User code
#include "api.h"

{
    auto en = Engine();
    auto usecase = en.getInstance(UseCase::USECASE1);
    //^^^ cannot be used before it is defined here    
    Process(usecase);
}

As I mentioned in the question, it is not desirable to expose UseCase1Impl and UseCase2Impl. How do I get past the error: function 'getInstance' with deduced return type cannot be used before it is defined

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

彡翼 2025-02-20 06:04:50

函数的返回类型是静态属性,它不能基于运行时数据更改。

如果可以的话,将USECASE提升到模板参数,并使用如果Constexpr为每个实例化完全具有一个活动返回。

template<UseCase a>
auto Engine::getInstance() {
    if constexpr (a == USECASE1)
        return UseCase1Impl(); // Defined in third_party.h and satisfies concept requirement.
    if constexpr (a == USECASE2)
        return UseCase2Impl();
}

如果您不能这样做,则必须找到一种常见的类型才能返回。

struct IProcessor
{
    virtual ~IProcessor() = default;
    virtual void init() = 0;
    virtual void process() = 0;
    virtual void deinit() = 0;
};

template <IsAProcessor T>
class ProcessorFacade : public IProcessor
{
    T impl;
public:
    template <typename... Args>
    ProcessorFacade(Args&&... args) : impl(std::forward<Args>(args)...) {}

    void init() final { impl.init(); }
    void process() final { impl.process(); }
    void deinit() final { impl.deinit(); }
};

std::unique_ptr<IProcessor> Engine::getInstance(UseCase a) {
    switch (UseCase) {
        case USECASE1:
            return std::make_unique<ProcessorFacade<UseCase1Impl>>();
        case USECASE2:
            return std::make_unique<ProcessorFacade<UseCase2Impl>>();
    }
}

The return type of a function is a static property, it can't change based on runtime data.

If you can, lift UseCase to a template parameter, and use if constexpr to have exactly one active return for each instantiation.

template<UseCase a>
auto Engine::getInstance() {
    if constexpr (a == USECASE1)
        return UseCase1Impl(); // Defined in third_party.h and satisfies concept requirement.
    if constexpr (a == USECASE2)
        return UseCase2Impl();
}

If you can't do that, you will have to find a common type to return.

struct IProcessor
{
    virtual ~IProcessor() = default;
    virtual void init() = 0;
    virtual void process() = 0;
    virtual void deinit() = 0;
};

template <IsAProcessor T>
class ProcessorFacade : public IProcessor
{
    T impl;
public:
    template <typename... Args>
    ProcessorFacade(Args&&... args) : impl(std::forward<Args>(args)...) {}

    void init() final { impl.init(); }
    void process() final { impl.process(); }
    void deinit() final { impl.deinit(); }
};

std::unique_ptr<IProcessor> Engine::getInstance(UseCase a) {
    switch (UseCase) {
        case USECASE1:
            return std::make_unique<ProcessorFacade<UseCase1Impl>>();
        case USECASE2:
            return std::make_unique<ProcessorFacade<UseCase2Impl>>();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文