C SFINAE с интерфейсом

#c #class #interface #shared-ptr #sfinae

#c #класс #интерфейс #общий -ptr #sfinae

Вопрос:

Я не могу понять, как я могу создать объект expr из double в expr.cpp досье.

expr_base:

Базовый класс всех выражений. Обратите внимание, что все классы выражений (включая эту базу) являются частными для реализации и не должны быть доступны для другого кода. Остальная часть программы должна использовать выражения только через expr .

Этот подкласс std::enable_shared_from_this позволяет получать shared_ptr для этого из метода.

выражение:

Обертка вокруг динамически выделяемых экземпляров expr_base . Этот тип имеет семантику значений, и поскольку все подклассы expr_base являются неизменяемыми, создаются мелкие копии.

Этот тип имеет перегруженные функции и операторы, так что построение выражений легко и читаемо.

ошибка:

      error: no viable conversion from returned value of type 'typename enable_if<!is_array<number>::value,
      shared_ptr<number> >::type' (aka 'std::__1::shared_ptr<exprs::number>') to function return type 'expr'
    return std::make_shared<exprs::number>(n);
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     /..../expr.hpp(...): note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'typename enable_if<!is_array<number>::value, shared_ptr<number> >::type' (aka 'std::__1::shared_ptr<exprs::number>') to 'const expr amp;' for 1st argument
class expr final {
      ^
     /.../expr.hpp:(...): note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'typename enable_if<!is_array<number>::value, shared_ptr<number> >::type' (aka 'std::__1::shared_ptr<exprs::number>') to 'expr amp;amp;' for 1st argument
    
     /.../expr.hpp:(...): note: candidate template ignored: requirement 'std::is_convertible<exprs::number *, const expr_base*>::value' was not satisfied [with T = exprs::number]
    expr(std::shared_ptr<T> e): ptr(std::static_pointer_cast<const expr_base>(std::move(e))) {}
 

выражение hpp

 ...
class expr;

class expr_base: public std::enable_shared_from_this<expr_base>
{
    friend class expr;
    protected:
        expr_base() = default;
    public:
        using variable_map_t = std::map<std::string, double>;
        virtual ~expr_base() = default;
};


class expr final {
    private:
        using const_pointer = std::shared_ptr<const expr_base>;
    public:
        using variable_map_t = expr_base::variable_map_t;

        template <typename T, typename = std::enable_if_t<std::is_convertible<T*, const expr_base*>::value>>
        expr(std::shared_ptr<T> e): ptr(std::static_pointer_cast<const expr_base>(std::move(e))) {}

        expr() = default;

        static expr number(double n);

        operator const_pointer const amp;() const {return ptr;}
        const expr_base* operator->() const {assert(ptr.get() != nullptr); return ptr.get();}
    private:
        const_pointer ptr;
};
 

expr.cpp

 ...
#include "expr.hpp"
#include "expr_impl.hpp"
    
expr expr::number(double n) {
    return std::make_shared<exprs::number>(n); // It doesn't work 
}
 

expr_impl.hpp

 ...
#include "expr.hpp"

namespace exprs {
    class number:expr_base {
    private:
        double num_;

    public:
        number(double num): num_(num) {};
    };
}
 

Комментарии:

1. class number:expr_base должен быть class number: public expr_base