I can't understand how i can create expr object from double in expr.cpp file.
expr_base:
The base class of all expressions. Note that all expression classes
(including this base) are private to the implementation and should not
be exposed to other code. The rest of the program should use
expressions only via expr.
This subclasses std::enable_shared_from_this to enable getting
shared_ptr to this from a method.
expr:
Wrapper around dynamically allocated instances of expr_base. This type
has value semantics and since all subclasses of expr_base are
immutable, shallow copies are made.
This type has overloaded functions and operators, so that expression
construction is easy and readable.
error:
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 &' 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 &&' 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))) {}
expr.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 &() 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) {};
};
}
Related
So I have an issue in converting between a base and derived class after adding some code to (de)serialize for JSON. I am using the nlohmann JSON library. For background, here is the general original set up (before the JSON code):
class Base;
class Derived : public Base;
std::unique_ptr<Derived> Foo(Node x) {
std::unique_ptr<Derived> result;
/* Set some fields */
return result;
}
std::unique_ptr<Base> NodeToBase(Node x) {
std::unique_ptr<Base> result = nullptr;
switch (x->type):
case (SomeType):
result = Foo(x);
return result;
}
Before adding the changes, the following assertions worked:
static_assert(std::is_convertible<Derived*, Base*>::value);
static_assert(std::is_convertible<std::unique_ptr<Derived>, std::unique_ptr<Base>>::value);
Next, I added some serialization functions to my base and derived classes as such:
class Base {
virtual nlohmann::json ToJson() const;
virtual void FromJson(const nlohmann::json &j);
}
class Derived : public Base {
nlohmann::json ToJson() const override;
void FromJson(const nlohmann::json &j) override;
}
I also removed any const quantifiers on member variables in Base and Derived to allow for deserialization.
And now, after compiling, the static_assert's above no longer worked, and I get the following error.
foo.cpp:155:14: error: no viable overloaded '='
result = Foo(x);
~~~~~~ ^ ~~~~~~~
/usr/local/Cellar/llvm#6/6.0.1/include/c++/v1/memory:2347:28: note: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'unique_ptr<Derived, default_delete<Derived>>' to 'const unique_ptr<Base, default_delete<Base>>' for 1st argument
class _LIBCPP_TEMPLATE_VIS unique_ptr {
^
/usr/local/Cellar/llvm#6/6.0.1/include/c++/v1/memory:2463:15: note: candidate function not viable: no known conversion from 'unique_ptr<Derived, default_delete<Derived>>' to 'unique_ptr<Base, default_delete<Base>>' for 1st argument
unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT {
^
/usr/local/Cellar/llvm#6/6.0.1/include/c++/v1/memory:2555:15: note: candidate function not viable: no known conversion from 'std::unique_ptr<Derived>' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
unique_ptr& operator=(nullptr_t) _NOEXCEPT {
^
/usr/local/Cellar/llvm#6/6.0.1/include/c++/v1/memory:2474:15: note: candidate template ignored: requirement 'is_convertible<typename unique_ptr<Derived, default_delete<Derived> >::pointer, pointer>::value' was not satisfied [with _Up = Derived, _Ep = std::__1::default_delete<Derived>]
unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT {
^
Any help would be appreciated. The only workaround I've found that works is to replace:
result = Foo(x);
with
result = std::unique_ptr<Base>(reinterpret_cast<Base *>(Foo(x).release()));
Consider the following snippet of code where I have a move-only Wrapper object that forwards the arguments to the underlying data on construction. Now if I use this Wrapper object inside another move-only class (SomeObject in this case), unless the move constructor for SomeObject is defaulted, it doesn't compile.
#include <utility>
template <typename T> class Wrapper {
public:
template <typename... Args>
Wrapper(Args &&... args) : _data{std::forward<Args>(args)...} {}
Wrapper(const Wrapper &) = delete;
Wrapper(Wrapper &&other) : _data(std::move(other)) {}
T &get() const { return _data; }
protected:
T _data;
};
struct SomeObject {
SomeObject(const SomeObject &) = delete;
SomeObject(SomeObject &&other) : x(std::move(other.x)) {}
//SomeObject(SomeObject &&other) = default; // this works!
SomeObject(int val) : x(val) {}
Wrapper<int> x;
};
int main() {
SomeObject obj(10);
return 0;
}
With gcc 6.3 we get:
test.cpp: In instantiation of ‘Wrapper<T>::Wrapper(Wrapper<T>&&) [with T = int]’:
test.cpp:20:56: required from here
test.cpp:10:52: error: cannot convert ‘std::remove_reference<Wrapper<int>&>::type {aka Wrapper<int>}’ to ‘int’ in initialization
Wrapper(Wrapper &&other) : _data(std::move(other)) {}
^
Is there something I am missing here? Aren't the user provided move constructor in SomeObject the same as the one the compiler would define when defaulted?
The only thing close to this that I could find is this answer but I feel like this is a different case since my move constructor for SomeObject isn't passing const types.
This is expected. Look at your code:
Wrapper(Wrapper &&other) : _data(std::move(other)) {}
T _data;
in your case, T is int. How do you want to initialize int from Wrapper<int>?
all. I am trying to learn something about template inherit. I want to cast a temp derived object to its base reference. But I come across this problem:
typedef long size64_t;
//////Base class
template <typename _Scalar>
class MatrixBase{
public:
virtual _Scalar operator()(size64_t rowid, size64_t colid) = 0;
};
//////Derived class 1
template <typename _Scalar>
class MatrixHolder : public MatrixBase<_Scalar>{
public:
MatrixHolder(){};
inline _Scalar operator()(size64_t rowid, size64_t colid){return 0;}
};
//////Derived class 2
template <typename _Scalar>
class Matrix : public MatrixBase<_Scalar>{
public:
Matrix(){};
inline _Scalar operator()(size64_t rowid, size64_t colid){return 0;}
};
//////The function with parameters as Base class reference, wanting to get derived object as input.
template <typename _Scalar>
MatrixHolder<_Scalar> apply(MatrixBase<_Scalar>& lhs, MatrixBase<_Scalar>& rhs){
MatrixHolder<_Scalar> result;
return result;
}
and in main, we have:
void main(){
Matrix<double> m1;
Matrix<double> m2;
apply(m1, m2);//Sucess
apply(m1, apply(m1, m2));//Fail
}
the compiler said:
note: candidate function [with _Scalar = double] not viable: no known conversion from
'MatrixHolder<double>' to 'MatrixBase<double> &' for 2nd argument
MatrixHolder<_Scalar> apply(MatrixBase<_Scalar>& lhs, MatrixBase<_Scalar>& rhs){
^
1 error generated.
apply(m1, apply(m1, m2));//Fail
The problem here is that the inner apply returns a temporary, which cannot bind to the non-const reference parameter of the outer apply.
If you can make the parameters MatrixBase<_Scalar> const& it would be a possible match.
I'm got a map of key type std::pair<Foo,Bar> and value in which I would like to insert into a map by passing the pair std::pair<std::pair<Foo,Bar> , int> to the insert function like so (online source)
struct Foo{};
struct Bar{};
typedef std::pair<Foo,Bar> FooBar;
typedef std::pair<FooBar,int> FooBarPair;
typedef std::map<FooBar,int> FooBarMap;
struct FooBarData
{
operator const FooBarPair() const
{
return std::make_pair( std::make_pair( m_foo , m_bar ) , m_num );
}
private:
int m_num;
Foo m_foo;
Bar m_bar;
};
int main()
{
FooBarData fbd;
FooBarMap fbm;
fbm.insert( fbd );
}
clang error message
/usr/include/c++/v1/map:1041:9: note: candidate function not viable: no known conversion from 'FooBarData' to 'const value_type' (aka 'const pair<const key_type, mapped_type>') for 1st argument
insert(const value_type& __v) {return __tree_.__insert_unique(__v);}
^
/usr/include/c++/v1/map:1050:14: note: candidate function template not viable: requires 2 arguments, but 1 was provided
void insert(_InputIterator __f, _InputIterator __l)
^
/usr/include/c++/v1/map:1045:9: note: candidate function not viable: requires 2 arguments, but 1 was provided
insert(const_iterator __p, const value_type& __v)
Is there any fix along these lines?
Add missing operator <.
Also, remove const from return type of conversion operator.
Edit After your change in Q:
You have to change your conversion to
operator std::pair<const FooBar, int>() const
Else, it would require 2 user conversions, which is not allowed.
Demo
(At least sometimes), the map implementations are/were red black trees. For map insert to work, your key type needs to support comparison (operator <). I cannot see this requirement to be met for your empty structs and the pair you create from them.
So as a first sanity check, I would replace Foo and Bar structs with
typedef int Foo;
typedef int Bar;
in order to see if something else is wrong with your code.
If it still is not compiling, check if std::pair<> supports comparison.
Also, instead of typedef'ing the FooBarPair yourself, you can simply enjoy that the map template already did that for you. For example:
...
operator FooBarMap::value_type() {
...
}
Here a fixed version, which compiles:
#include <map>
struct Foo { int x; };
struct Bar {};
typedef std::pair<Foo, Bar> FooBar;
typedef std::map<FooBar, int> FooBarMap;
bool operator <(const FooBarMap::key_type&lhs, const FooBarMap::key_type& rhs)
{
return lhs.first.x < rhs.first.x;
}
struct FooBarData
{
operator FooBarMap::value_type() const
{
return FooBarMap::value_type(FooBarMap::key_type(m_foo, m_bar), m_num);
}
private:
int m_num;
Foo m_foo;
Bar m_bar;
};
int main()
{
FooBarData fbd;
FooBarMap fbm;
fbm.insert(fbd);
}
I am unable to write a correct user defined conversion for a type Item. This is what I've tried:
#include <iostream>
#include <boost/optional.hpp>
struct A
{
int x;
};
struct Item
{
boost::optional<int> x_;
Item(){}
Item(const A& s)
: x_(s.x)
{
}
operator boost::optional<A>() const {
boost::optional<A> s;
if (x_) {
s->x = *x_;
}
return s;
}
};
std::vector<A> getA(const std::vector<Item> &items) {
std::vector<A> a;
for (const auto &i : items) {
if (i.x_) {
a.push_back(*static_cast<boost::optional<A>>(i)); // <- this line causes error
}
}
return a;
}
That is how I use it:
int main() {
A a;
a.x = 3;
Item i(a);
auto v = getA({i});
return 0;
}
g++ -std=c++11 says:
In file included from /usr/include/boost/optional.hpp:15:0,
from test.cpp:2:
/usr/include/boost/optional/optional.hpp: In instantiation of ‘void boost::optional_detail::optional_base<T>::construct(const Expr&, const void*) [with Expr = Item; T = A]’:
/usr/include/boost/optional/optional.hpp:262:25: required from ‘boost::optional_detail::optional_base<T>::optional_base(const Expr&, const Expr*) [with Expr = Item; T = A]’
/usr/include/boost/optional/optional.hpp:559:78: required from ‘boost::optional<T>::optional(const Expr&) [with Expr = Item; T = A]’
test.cpp:30:55: required from here
/usr/include/boost/optional/optional.hpp:392:8: error: no matching function for call to ‘A::A(const Item&)’
new (m_storage.address()) internal_type(expr) ;
^
/usr/include/boost/optional/optional.hpp:392:8: note: candidates are:
test.cpp:3:8: note: A::A()
struct A
^
test.cpp:3:8: note: candidate expects 0 arguments, 1 provided
test.cpp:3:8: note: constexpr A::A(const A&)
test.cpp:3:8: note: no known conversion for argument 1 from ‘const Item’ to ‘const A&’
test.cpp:3:8: note: constexpr A::A(A&&)
test.cpp:3:8: note: no known conversion for argument 1 from ‘const Item’ to ‘A&&’
Why does it try to find A struct constructor instead of use user defined conversion operator?
You may point me directly to any position of the user-defined conversion page because I am unable to find any reason for this. For example,
User-defined conversion function is invoked on the second stage of the implicit conversion, which consists of zero or one converting constructor or zero or one user-defined conversion function.
in my opinion directly says that if no conversion constructor is defined then user-defined conversion function will be used. Am I wrong? And if yes, how can I implement user-defined conversion then without defining conversion cunstructor in struct A ?
You have two issues with your code. Your optional operator never initializes the boost::optional. If you don't do that, accessing members is undefined behavior. What you have to do is:
operator boost::optional<A>() const {
boost::optional<A> s;
if (x_) {
s = A{*x_};
}
return s;
}
The second issue is when you do:
static_cast<boost::optional<A>>(i);
That is equivalent to:
boost::optional<A> __tmp(i);
But it turns out that boost::optional has an explicit template constructor. That will be preferred to your conversion function. The error you're seeing is the compiling going down the path of this factory constructor, where Item is not such a factory.
You could simply use boost::optional<A> directly:
std::vector<A> getA(const std::vector<Item> &items) {
std::vector<A> a;
for (boost::optional<A> opt : items) {
if (opt) {
a.push_back(*opt);
}
}
return a;
}
Or, since the constructor template is explicit, you could use the conversion operator in a non-explicit context:
boost::optional<A> opt = i;
a.push_back(*opt);
This has the added benefit of also being easier to read.