These are chat archives for symengine/symengine

28th
Apr 2016
Isuru Fernando
@isuruf
Apr 28 2016 03:41
@StoicBronco, I'll review it soon
Isuru Fernando
@isuruf
Apr 28 2016 09:55
@bluescarni, I'm using gcc-4.7 and I need to replicate constructor forwarding for CRTP visitor
Francesco Biscani
@bluescarni
Apr 28 2016 09:56
you want to emulate something like inheriting ctors in GCC 4.7?
Isuru Fernando
@isuruf
Apr 28 2016 09:56
What I've done is
using enable_if_t = typename std::enable_if<B,T>::type;

template <class Derived, class Base = Visitor>
class BaseVisitor : public Base
{

public:
    template <typename... Args, typename = enable_if_t<std::is_constructible<Base, Args...>::value>>
        BaseVisitor(Args &&... args)
        : Base(std::forward<Args>(args)...)
    {
    }
}
yes
inheriting ctors
Francesco Biscani
@bluescarni
Apr 28 2016 09:57
basically what you need to be careful about is that it does not overshadow the copy/move ctors
at least I prefer to have them separate
Isuru Fernando
@isuruf
Apr 28 2016 09:58
Problem with my code is it gives an error when the Base class has an implicit default constructor
I'll have a look at the piranha code
Francesco Biscani
@bluescarni
Apr 28 2016 09:58
what kind of error?
Isuru Fernando
@isuruf
Apr 28 2016 10:01
/home/isuru/projects/symengine/symengine/series.cpp:25:35: error: use of deleted function ‘SymEngine::NeedsSymbolicExpansionVisitor::NeedsSymbolicExpansionVisitor()’
     NeedsSymbolicExpansionVisitor v;
                                   ^
In file included from /home/isuru/projects/symengine/symengine/series.cpp:9:0:
/home/isuru/projects/symengine/symengine/series_visitor.h:289:7: note:SymEngine::NeedsSymbolicExpansionVisitor::NeedsSymbolicExpansionVisitor()’ is implicitly deleted because the default definition would be ill-formed:
 class NeedsSymbolicExpansionVisitor
Problem is that the default constructor of BaseVisitor is deleted
Francesco Biscani
@bluescarni
Apr 28 2016 10:04
can you post more lines of the log?
Isuru Fernando
@isuruf
Apr 28 2016 10:06
/home/isuru/projects/symengine/symengine/visitor.h:50:7: note:   candidate expects 1 argument, 0 provided
/home/isuru/projects/symengine/symengine/series.cpp: In function ‘bool SymEngine::needs_symbolic_constants(const SymEngine::RCP<const SymEngine::Basic>&, const SymEngine::RCP<const SymEngine::Symbol>&)’:
/home/isuru/projects/symengine/symengine/series.cpp:25:35: error: use of deleted function ‘SymEngine::NeedsSymbolicExpansionVisitor::NeedsSymbolicExpansionVisitor()’
     NeedsSymbolicExpansionVisitor v;
                                   ^
In file included from /home/isuru/projects/symengine/symengine/series.cpp:9:0:
/home/isuru/projects/symengine/symengine/series_visitor.h:289:7: note:SymEngine::NeedsSymbolicExpansionVisitor::NeedsSymbolicExpansionVisitor()’ is implicitly deleted because the default definition would be ill-formed:
 class NeedsSymbolicExpansionVisitor
       ^
/home/isuru/projects/symengine/symengine/series_visitor.h:289:7: error: no matching function for call to ‘SymEngine::BaseVisitor<SymEngine::NeedsSymbolicExpansionVisitor, SymEngine::StopVisitor>::BaseVisitor()’
In file included from /home/isuru/projects/symengine/symengine/series_visitor.h:5:0,
                 from /home/isuru/projects/symengine/symengine/series.cpp:9:
/home/isuru/projects/symengine/symengine/visitor.h:55:9: note: candidate: template<class ... Args, class> SymEngine::BaseVisitor<Derived, Base>::BaseVisitor(Args&& ...)
         BaseVisitor(Args &&... args)
         ^
/home/isuru/projects/symengine/symengine/visitor.h:55:9: note:   template argument deduction/substitution failed:
/home/isuru/projects/symengine/symengine/visitor.h:50:7: note: candidate: constexpr SymEngine::BaseVisitor<SymEngine::NeedsSymbolicExpansionVisitor, SymEngine::StopVisitor>::BaseVisitor(const SymEngine::BaseVisitor<SymEngine::NeedsSymbolicExpansionVisitor, SymEngine::StopVisitor>&)
 class BaseVisitor : public Base
       ^
/home/isuru/projects/symengine/symengine/visitor.h:50:7: note:   candidate expects 1 argument, 0 provided
/home/isuru/projects/symengine/symengine/visitor.h:50:7: note: candidate: constexpr SymEngine::BaseVisitor<SymEngine::NeedsSymbolicExpansionVisitor, SymEngine::StopVisitor>::BaseVisitor(SymEngine::BaseVisitor<SymEngine::NeedsSymbolicExpansionVisitor, SymEngine::StopVisitor>&&)
Francesco Biscani
@bluescarni
Apr 28 2016 10:07
right so it looks like BaseVisitor has no default ctor available?
Isuru Fernando
@isuruf
Apr 28 2016 10:08
Yes, but I don't want it to be there if Base doesn't
Francesco Biscani
@bluescarni
Apr 28 2016 10:09
but NeedsSymbolicExpansionVisitor needs a default constructor apparently, so the problem is that NeedsSymbolicExpansionVisitor is somehow trying to instantiate the ctor of Base?
Isuru Fernando
@isuruf
Apr 28 2016 10:10
no, it's trying to instantiate the ctor of BaseVisitor
Francesco Biscani
@bluescarni
Apr 28 2016 10:12
ok so the problem is that the default ctor of BaseVisitor should not be there
Isuru Fernando
@isuruf
Apr 28 2016 10:13
NeedsSymbolicExpansionVisitor <- BaseVisitor <- StopVisitor
StopVisitor has an implicit default constructor. NeedsSymbolicExpansionVisitor too, but BaseVisitor doesn't
because of the templated constructor of BaseVisitor
If I do this, everything works
using enable_if_t = typename std::enable_if<B,T>::type;

template <class Derived, class Base = Visitor>
class BaseVisitor : public Base
{

public:
    template <typename... Args, typename = enable_if_t<std::is_constructible<Base, Args...>::value>>
        BaseVisitor(Args &&... args)
        : Base(std::forward<Args>(args)...)
    {
    }

    BaseVisitor() : Base() {}
}
Francesco Biscani
@bluescarni
Apr 28 2016 10:17
so I remember vaguely that templated ctors do no inhibit the declaration of default constructors
or something along these lines
let me dig a second

http://stackoverflow.com/questions/5367036/derived-assignment-operator-and-perfect-forwarding if you look at the reply he says:

The generation of an implicit move assignment operator is only inhibited if the user declares a copy assignment operator, move assignment operator, copy constructor, move constructor or destructor. None of these special members can be a template. [class.copy] enumerates the forms for each of these special members.
For example a move assignment operator for class X will have one of the following forms:
operator=(X&&);
operator=(const X&&);
operator=(volatile X&&);
operator=(const volatile X&&);
(any return type can be used).
The templated assignment operator in bar does not qualify as a special member. It is not a copy assignment operator nor a move assignment operator.

so I think that even if you defined the template ctor in BaseVisitor, the default ctor still gets generated automatically by the compiler and it is preferred over the templated one
I don't know how this exactly interacts with your design, maybe it doesn't :)
but I thought it would be useful for you to know
Francesco Biscani
@bluescarni
Apr 28 2016 10:23
do you have the code up somewhere?
Isuru Fernando
@isuruf
Apr 28 2016 10:24
let me push the code
See symengine/visitor.h
Francesco Biscani
@bluescarni
Apr 28 2016 10:29
you also have a test case in the tests already?
Isuru Fernando
@isuruf
Apr 28 2016 10:30
yes
Francesco Biscani
@bluescarni
Apr 28 2016 10:38
so here's what I think it is going on: when you declare any constructor, the implicit generation of the default constructor is inhibited http://en.cppreference.com/w/cpp/language/default_constructor#Implicitly-declared_default_constructor
Isuru Fernando
@isuruf
Apr 28 2016 10:39
Yes, but Base has a default constructor, so shouldn't that be used in BaseVisitor templated ctor?
Francesco Biscani
@bluescarni
Apr 28 2016 10:39
I think that maybe template ctors cannot be considered as default constructors
Isuru Fernando
@isuruf
Apr 28 2016 10:41
Or if the templated ctor can act as a default constructor and the compiler adds a default ctor, there's an ambiguity
Francesco Biscani
@bluescarni
Apr 28 2016 10:42
that is what I was thinking in the beginning, but the error messages of both GCC and clang do not hint to ambiguities
doing some experiments
Isuru Fernando
@isuruf
Apr 28 2016 10:44
This line is what made me think that,
note: ‘SymEngine::NeedsSymbolicExpansionVisitor::NeedsSymbolicExpansionVisitor()’ is implicitly deleted because the default definition would be ill-formed:
Anyway, this should go away when we upgrade to gcc-4.8. Just using Base::Base; would do
gcc-4.7 is still used in Ruby wrappers for windows, that's why gcc-4.7 is used
Francesco Biscani
@bluescarni
Apr 28 2016 10:49
In file included from /home/yardbird/temp/symengine/symengine/basic.cpp:13:
/home/yardbird/temp/symengine/symengine/subs.h:16:5: error: constructor for 'SymEngine::SubsVisitor' must explicitly initialize the base class 'BaseVisitor<SymEngine::SubsVisitor>' which does not have a default constructor
    SubsVisitor(const map_basic_basic &subs_dict) : subs_dict_(subs_dict)
    ^
/home/yardbird/temp/symengine/symengine/visitor.h:48:7: note: 'SymEngine::BaseVisitor<SymEngine::SubsVisitor, SymEngine::Visitor>' declared here
class BaseVisitor : public Base
      ^
/home/yardbird/temp/symengine/symengine/basic.cpp:35:16: error: call to implicitly-deleted default constructor of 'SymEngine::StrPrinter'
    StrPrinter strPrinter;
               ^
/home/yardbird/temp/symengine/symengine/printer.h:156:20: note: default constructor of 'StrPrinter' is implicitly deleted because base class 'BaseVisitor<SymEngine::StrPrinter>' has no default constructor
class StrPrinter : public BaseVisitor<StrPrinter>
                   ^
2 errors generated.
this is what clang says
Isuru Fernando
@isuruf
Apr 28 2016 10:50
Right. so default constructor is deleted and the templated ctor cannot act like one.
Francesco Biscani
@bluescarni
Apr 28 2016 10:51
it would seem so but I cannot reproduce the behaviour in a minimal example
#include <iostream>

struct foo
{
        template <typename ... Args>
        foo(Args && ...)
        {
                std::cout << "variadic called\n";
        }
        //foo() = delete;
};

int main()
{
        foo f;
}
so this works as expected, it prints variadic called
but if you uncomment the line it fails to compile
if you use foo() = default it compiles and nothing is printed
Francesco Biscani
@bluescarni
Apr 28 2016 11:02
actually
if you comment out the enable_if in the variadic ctor it does work as expected
Isuru Fernando
@isuruf
Apr 28 2016 11:04
Even this works
#include <type_traits>

template <bool B, class T = void>
using enable_if_t = typename std::enable_if<B, T>::type;

#include <iostream>

class Bar {

};

template <typename T>
class Foo : public T
{
public:
        template <typename ... Args, typename = enable_if_t<std::is_constructible<T, Args...>::value>>
        Foo(Args && ... args) : T(std::forward<Args>(args)...)
        {
                std::cout << "variadic called\n";
        }
        //Foo() = delete;
};

class FooBar : Foo<Bar> {
};

int main()
{
        FooBar f;
}
Francesco Biscani
@bluescarni
Apr 28 2016 11:06
maybe we are getting somewhere, I think it might have to do with the abstractness of Base
what might be happening is that the enable_if does not detect Base as ctible
because it has pure virtual methods
Isuru Fernando
@isuruf
Apr 28 2016 11:09
Yes, making Bar abstract will generate the failure
Francesco Biscani
@bluescarni
Apr 28 2016 11:09
right.... enable_if cannot possibly know that you will implement the abstract methods in BaseVisitor
I think I'd just use BaseVisitor() = default;
this will be preferred to the template ctor if Base is def ctible, if not it should disappear and yield to the templated ctor
but possibly the best fix is to upgrade to GCC 4.8 :)
Isuru Fernando
@isuruf
Apr 28 2016 11:17
Thanks for the input.
It would probably be a good idea to move to GCC 4.8
Francesco Biscani
@bluescarni
Apr 28 2016 11:18
np
yeah
I was still a bit unconvinced by inheriting ctors last time I tried, but probably piranha's use cases are a bit peculiar in that respect
it's also not using virtual anywhere so I never ran into this specific issue, which is rather quirky
Isuru Fernando
@isuruf
Apr 28 2016 14:41
BaseVisitor() = default; leads to an error with MSVC. So, I'll have to use the earlier version
Francesco Biscani
@bluescarni
Apr 28 2016 14:41
ouch... is that MSVC 2015?
Isuru Fernando
@isuruf
Apr 28 2016 14:42
error C2580: 'SymEngine::BaseVisitor<SymEngine::SubsVisitor,SymEngine::Visitor>::BaseVisitor(void)': multiple versions of a defaulted special member functions are not allowed [C:\projects\symengine\build\symengine\symengine.vcxproj]
yes
Francesco Biscani
@bluescarni
Apr 28 2016 14:42
:(
Isuru Fernando
@isuruf
Apr 28 2016 14:42
MSVC2015 do support inheriting ctors though
Ralf Stephan
@rwst
Apr 28 2016 15:10

So, since flint2 github trunk is switched to LGPL, as was arb master two days ago, and the question of SymEngine requiring both was answered conditionally on this, it remains for symengine to do the transition to require both libraries. For devs this just means that generic implementations won't be needed if there is a flint/arb version in SymEngine. The actual switch, i.e., to stop compilation if flint could not be found first depends on a new flint version released at all.

@certik When thinking of this why was linking with old versions not a problem before? (IANAL) Why was the switch by flint necessary? Can you give a hypothetical example?