bluescarni / obake

A C++20 library for the symbolic manipulation of sparse polynomials & co.

Home Page:https://bluescarni.github.io/obake

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

msvc compilation error

andrewcorrigan opened this issue · comments

Compiled with VS2019 Version 16.7.2, MSVC 19.27.29110.0, with flags /std:c++17 /Zc:__cplusplus

Minimal reproducer:

#ifndef NOMINMAX
#  define NOMINMAX
#endif

#ifndef WIN32_LEAN_AND_MEAN
#  define WIN32_LEAN_AND_MEAN
#endif

#include <mp++/integer.hpp>
#include <mp++/rational.hpp>

#include <obake/polynomials/d_packed_monomial.hpp>
#include <obake/polynomials/polynomial.hpp>

int main(int argc, char** argv)
{
    using Rational = mppp::rational<1>;
    using Integer = mppp::integer<1>;

    using Monomial = obake::d_packed_monomial<unsigned long, 8>;
    using Polynomial = obake::polynomial<Monomial, Rational>;

    return 0;
}

Error message:

1>\obake\include\obake/series.hpp(141,60): error C2938: 'std::enable_if_t<false,void>' : Failed to specialize alias template
1>\obake\include\obake/series.hpp(141): message : see reference to alias template instantiation 'std::enable_if_t<false,void>' being compiled
1>test.cpp(22): message : see reference to alias template instantiation 'obake::polynomial<Monomial,Rational>' being compiled
1>\obake\include\obake/polynomials/polynomial.hpp(86,20): error C2976: 'obake::series': too few template arguments
1>\obake\include\obake/series.hpp(688): message : see declaration of 'obake::series'

The error points to this line:

template <typename K, typename C, typename, typename = ::std::enable_if_t<::std::conjunction_v<is_key<K>, is_cf<C>>>>

The problem seems to be that either Rational is not recognized as a coefficient type, or Monomial is not recognized as a key type.

What do these line output?

std::cout << obake::is_cf<Rational>::value << '\n';
std::cout << obake::is_key<Monomial>::value << '\n';

It printed out:

1
0

Just for my reference, I changed the code to:

#ifndef NOMINMAX
#  define NOMINMAX
#endif

#ifndef WIN32_LEAN_AND_MEAN
#  define WIN32_LEAN_AND_MEAN
#endif

#include <mp++/integer.hpp>
#include <mp++/rational.hpp>

#include <obake/polynomials/d_packed_monomial.hpp>
#include <obake/polynomials/polynomial.hpp>


int main(int argc, char** argv)
{
    using Rational = mppp::rational<1>;
    using Integer = mppp::integer<1>;

    using Monomial = obake::d_packed_monomial<unsigned long, 8>;
    //using Polynomial = obake::polynomial<Monomial, Rational>;

    std::cout << obake::is_cf<Rational>::value << '\n';
    std::cout << obake::is_key<Monomial>::value << '\n';

    return 0;
}

Ok, so it seems for some reason Monomial does not satisfy the is_key requirements. The next step would be to go here:

https://github.com/bluescarni/obake/blob/master/include/obake/series.hpp#L99

and start commenting out one by the type traits in that std::conjunction<>, and then check again (using the main() you posted above) which type trait makes is_key return false.

I had to comment out all but two. Uncommenting any of the others leads to is_key returning false.

template <typename T>
using is_key = ::std::conjunction<is_semi_regular<T>, ::std::is_constructible<T, const symbol_set &>,
                                  //is_hashable<::std::add_lvalue_reference_t<const T>>,
                                  is_equality_comparable<::std::add_lvalue_reference_t<const T>>,
                                  //is_zero_testable_key<::std::add_lvalue_reference_t<const T>>,
                                  //is_one_testable_key<::std::add_lvalue_reference_t<const T>>,
                                  //is_compatibility_testable_key<::std::add_lvalue_reference_t<const T>>,
                                  //is_stream_insertable_key<::std::add_lvalue_reference_t<const T>>,
                                  std::true_type>;

The code is now just:

#ifndef NOMINMAX
#  define NOMINMAX
#endif

#ifndef WIN32_LEAN_AND_MEAN
#  define WIN32_LEAN_AND_MEAN
#endif

#include <obake/polynomials/d_packed_monomial.hpp>
#include <obake/series.hpp>

int main(int argc, char** argv)
{
    using Monomial = obake::d_packed_monomial<unsigned long, 8>;

    std::cout << obake::is_key<Monomial>::value << '\n';

    return 0;
}

Thanks for checking. This looks pretty bad, it seems like the obake concept emulation layer is not working at all. Is this a stable version of MSVC or a beta/developer preview? I am gonna try pinging @7ofNine as he has also been compiling obake on Windows for a while.

As a last resort, could you try to use /std:c++latest instead of /std:c++17?

It's 16.7.2, which it looks like is the latest release.. Maybe I should try the 16.8 preview instead, if I can get access?

In terms of testing with /std:c++latest, unfortunately I can't easily do that: /std:c++latest breaks Abseil since std::result_of has been removed. I'm not sure how to replace it with std::invoke_result. I have one big cmake project for Obake and its dependencies, so I can't easily separate Abseil from Obake.

In terms of being a practical workaround, unfortunately, from testing other code (not using Obake), I found that /std:c++latest is extremely buggy and generally unusable, even in ways unrelated to any C++20 features. On the other hand, I was able to get my other code compiling with /std:c++17, so for now, that's my only viable option.

I will try if I can find something. I recommend against using /std:c++latest besides that abseil has issues with not using result_of which has been removed from std (and is trivial to fix, I think there is also a define one can use to overwrite that) there are permanenteley other actual compiler issues. I haven't been able to compile obake with it in a while. I also typically work at the front with the latest previews. Quite often there are issues with the lambda capture and for a while there were lot's of issues with SFINAE and I don't remember when they got fixed. I still have an open issue with MS that is hanging there since January 2019.
What I can say is that not having programmed anything outside of the tests for obake and/or mp++ that those compile and run under c++17 in MSVC. I will try the above example with the latest 19.8 preview 2 and report back the result.

I just got the preview installed (VS 2019 16.8 preview 2). Unfortunately, it's still broken with /std:c++17.

@7ofNine thanks for looking into this! If the obake tests pass in c++17 mode, I would assume that Andrew's example also passes, as similar code is instantiated often in the examples.

@andrewcorrigan in terms of practical workarounds, if it is an option for you I'd try the clang + MSVC combination, which, as far as modern C++ goes, is much smoother sailing.

clang + MSVC means using clang as a compiler on top of the MSVC standard library, this gives you binary compatibility with other MSVC-compiled code but much better standard conformance and fewer bugs.

Thank you. I was hoping to just stick to the "system-default", but that sounds like an easier approach. When I tried it out real quick, cmake ignored my specification of clang++.exe and just used cl.exe. I'll dig deeper and figure that out.

I just ran all the tests using MSVC 19.8 preview 2 using C++17 and they have no problem. All 73 tests ran in 9.01s.

Does my example build for you? It would be great if I just screwed something up...

sorry to say but I have no problems with the compilation an it runs without an exception.

`1>------ Rebuild All started: Project: test_gitissue, Configuration: Release x64 ------
1>test_gitissue.cpp
1>Generating code
1>Previous IPDB not found, fall back to full compilation.
1>All 7 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
1>Finished generating code
1>test_gitissue.vcxproj -> D:\Dev\Astronomy\obaker-build-VS2019-64\x64\Release\test_gitissue.exe
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

`
and this is just the result of a copy and paste from the example above.
And the result is the same with setting explicitly /Zc:__cplusplus, which I never do.

So the good news is that it works and can give the standard IT answer "it should work", which doesn't solve your problem.
Having meanwhile experienced many of this type of completely unexplainable errors it will be a little bit of a hunt to probably find the pretty trivial reason.

Using the reference above compiles and runs with correct results

`1
1

D:\Dev\Astronomy\obaker-build-VS2019-64\x64\Release\test_gitissue.exe (process 3
264) exited with code 0.
Press any key to close this window . . .

`

How do you guys install dependencies (gmp, mpfr, boost, tbb, abseil) on Windows for running the tests? I'd like to make sure I'm installing all the dependencies in exactly the same way. I'll avoid cmake and create a VS solution manually (in case it's setting some flags inappropriately).

Not that I haven't done that but I just checked. I am on the latest master form 11/06/2020
Commit hash: 3fbf54b

I also found that I had a small change in one of the files behind the C++20 with concepts macro and removed it. Rebuild of obake and test runs are fine and your problem doesn't pop up either.
My project settings are nothing exotic. I just created a project from scratch as Visual Studio does it, changes the language standard to C++17, made it compile as C++ (/TP), and added all the needed include directories and the single link library needed. But you don't even get to the point of linking.

thanks, I'll give it a shot.

For the dependencies CMAKE as it is works just fine (except for some pthread issue I always forget about but I think that is with mp++ and Flint not with obake.)
For all the dependencies I use my own built versions which are not necessarily the latest master versions available but typically are not too far away. For gmp I actually use mpir and also the mpfr incarnation for windows both provided by Gladman. These dependencies are build and installed (if they have the provision for it). There are sometimes some small issues with the installations because some files are missing etc., just showing that Windows support ranks second, but in general it is not too difficult to make them work. TBB is probably the one I haven't touched for the longest time.

BTW the /TP is not really necessary. VC is smart enough to detect it by itself. It is just for the rare code that looks the same in C and C++.

How do you guys install dependencies (gmp, mpfr, boost, tbb, abseil) on Windows for running the tests? I'd like to make sure I'm installing all the dependencies in exactly the same way. I'll avoid cmake and create a VS solution manually (in case it's setting some flags inappropriately).

I normally use the conda package manager for the dependencies. This is what is being used on the CI as well, see e.g. here for the command that installs the deps:

https://github.com/bluescarni/obake/blob/master/appveyor.yml#L20

See here for the conda docs:

https://docs.conda.io/en/latest/

Thanks again, to both of you.

I tried installing the dependencies from conda and all of the obake tests passed. I then tried out my reproducers above as well. The original one compiled, and the latest one reports that everything is working fine. Therefore, either my build of the dependencies are messed up, or my project's cmake configuration is triggering some sort of issue.

Please feel free to close this if you consider this outside of the scope of Obake and merely a user error.

However, I will report back what this turns out to be, and perhaps there might be a way Obake can be made a bit more resilient to whatever user-error that I have made.

We can keep the report open for the time being, I would also be interested to understand what is going on.

I finally tracked down the problem: I did not have the flag /permissive- set. This flag is set when building Obake, but not my code that uses Obake. With that flag enabled, my code compiles fine.

Ok good to hear that you got to the bottom of it. I'll add some extra warning in the docs.

I will close the issue then.