I am trying to port some C++17 code I made on ubuntu (gnu++11)
typedef boost::variant<int, float, std::string > Variant;
using Func = std::function<std::vector<unsigned char>(std::vector<Variant>)>;
void addexecutorfunc( Func callback, const auto&...args )
{
std::vector<Variant> vec = {args...};
executor.add(vec, std::move(callback));
}
this code compiles and works fine on ubuntu, but when trying to compile on windows with visual studio 2017(v141) [ISO C++ Latest Draft Standard(/std:c++latest)], then I get following:
error C3533: a parameter cannot have a type that contains 'auto'
I think perhaps it has to do with the Concepts lite not being implemented in current C++17 version or is this wrong?
If I could setup compiler to use auto as parameter and parameter packs, then that would be best, but if this is not possible, then I will have to rewrite my code to follow C++17 windows standard - any suggestions on how to do this without ending up in a template hell
void addexecutorfunc( Func callback, const auto&...args )
auto as a parameter to a (non-lambda) function is a GNU extension. It is not part of standard C++17, and is not supported by either of the other two major C++ compilers, Clang and MSVC. Rather unfortunately, GCC seems to allow it in -std=c++14 mode as well as with -std=gnu++14.
The standard C++ equivalent would be a function template
template <typename... Ts>
void addexecutorfunc(Func callback, const Ts&... args)
which should work as expected.
Related
I'm currently trying to deduce a std::tuple type from several std::vectors that are passed as parameters. My code works fine using gcc, but the compilation fails with Visual Studio Professional 2019 with the message "fatal error C1202: recursive type or function dependency context too complex".
It has been mentioned for my previous post (C++ "fatal error C1202: recursive type or function dependency context too complex" in visual studio, but gcc compiles) that the problem is caused by template recursion as explained in C++ template compilation error - recursive type or function dependency. However, I don't see where the recursion occurs.
So my questions are:
Why is there an (infinite) recursion?
How can it be resolved?
Here is the code (I'm bound to C++11):
#include <tuple>
#include <vector>
template <typename TT,typename Add>
auto addTupBase(TT t,std::vector<Add> a) ->decltype (std::tuple_cat(t,std::make_tuple(a[0])))
{
return std::tuple_cat(t,std::make_tuple(a[0])) ;
}
template <typename TT,typename Add,typename... Args>
auto addTupBase(TT t,std::vector<Add> a,Args... args)-> decltype(addTupBase(addTupBase(t,a),args...))
{
return addTupBase(addTupBase(t,a),args...);
}
template <typename T,typename... Args>
auto addTup(std::vector<T> in,Args... args) ->decltype(addTupBase(std::make_tuple(in[0]),args...))
{
return addTupBase(std::make_tuple(in[0]),args...);
}
int main()
{
using TupleType = decltype(addTup(std::vector<char>{2},std::vector<int>{5},std::vector<double>{32423}));
TupleType t;
std::get<2>(t) = 342.2;
return 0;
}
MSVC has some conformance issues when running in /permissive mode and "The Microsoft C++ compiler doesn't currently support binding nondependent names when initially parsing a template. This doesn't conform to section 14.6.3 of the C++ 11 ISO specification. This can cause overloads declared after the template (but before the template is instantiated) to be seen.".
If you instead use /permissive- "The compiler [...] implements more of the requirements for two-phase name look-up" and will compile your program as-is.
Also note that you aren't actually using C++11. MSVC 19.24 supports C++14 and up.
The following minimal example does not build on current MSVC 2017 (19.16). It does build on MSVC 2015 and older versions of 2017 (19.14), GCC, Clang, and ICC. So I suspect it is a compiler bug. Is it valid? If not, why?
#include <array>
#include <utility>
template<int... Is>
auto foo(std::integer_sequence<int, Is...>)
{
return std::array<int, unsigned(sizeof...(Is))>{ Is... };
}
std::array<int, 3> bar()
{
return foo(std::make_integer_sequence<int, 3>());
}
Variants that do work:
Putting unsigned(sizeof...(Is)) in the parameter list as a defaulted parameter
Replacing unsigned(...) with static_cast<unsigned>(...)
Removing the cast (not a solution in the real world code, only in the minimal example)
Definitely a compiler bug. However, it seems to have been fixed. Builds here with Visual Studio 2019 (MSVC version 19.20.27508.1)…
gcc's treatment of variadic templates is well known to be patchy (see for example this and this), but I wonder whether the following bug is already known (I cannot find it at bugzilla) or whether it is indeed a bug. Essentially, gcc (4.8.1) fails to expand a parameter pack inside a lambda:
#include <vector>
#include <algorithm>
#include <type_traits>
template<typename T, typename F, typename... X>
void bar(std::vector<T> const&c, F const&f, X&&... x)
{
std:for_each(c.begin(),c.end(),[&](const T&t)
{ f(t,std::forward<X>(x)...); });
}
this causes (even without any instantiation)
error: parameter packs not expanded with ‘...’:
{ f(t,std::forward<X>(x)...); });
^
any idea how to avoid that? (note: okay with icpc 14.0.2 and clang 3.4) Or is gcc correct after all and clang & icpc wrong?
edit Note that the problem is the lambda, as also this doesn't compile:
template<typename T, typename F, typename... X>
void bar(std::vector<T> const&c, F const&f, X&&... x)
{
auto func = [&](const T&t){ f(t,std::forward<X>(x)...); };
std:for_each(c.begin(),c.end(),func);
}
with the "error" report in the lambda defiition.
Given that the code compiles cleanly with both clang version 3.5 (trunk 202594) and more importantly with gcc version 4.9.0 20140302 (experimental) (GCC), both with -Wall, I would say it was an issue with the earlier versions of gcc.
I am looking for a gcc bugreport at http://gcc.gnu.org/bugzilla/ to confirm this.
The following code gives compilation errors on both MSVC++ 2012 CTP (with C+11 support) and Intel C++ XE 13.0:
template <typename F, typename... Args>
void apply(F f, std::tuple<Args...>& args) {
// doesn't do much yet
}
bool f1(char c) {
return c == 'c';
}
int main(int argc, char* argv[]) {
auto t = std::make_tuple('c');
apply(f1, t);
return 0;
}
VS2012 error is:
error C2243: 'type cast' :
conversion from 'std::tuple<char,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil> *'
to 'std::tuple<std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil> &' exists,
but is inaccessible
Error on Intel C++ XE 13.0 is:
error : no instance of function template "apply" matches the argument list
What am I missing? Are there really errors here, or do I just have two bad compilers?
UPDATE: Same (or similar) results when I use boost::tuple instead of std::tuple on both compilers.
ADDENDUM: Thanks for all the cross-checks in the comments. I've sent bug reports to both of these fine corporations.
That is likely a VC11 bug in the implementation of the Standard Library. Although the CTP supports variadic templates, to the best of my knowledge the Standard Library was not rewritten to use them and adopts some machinery to simulate variadic templates. This is likely at the origin of your problem.
I'm having trouble working with lambda functions in the Intel compiler, in particular, the following code won't compile:
template<typename T>
std::function<T (int)> make_func(T x) {
return [=](int index) -> T
{
return x;
};
}
The error I get is
error: namespace "std" has no member "function"
The code compiles and runs fine on my Mac, (macports gcc version 4.5). The error is at work, where we use the Intel compiler version 11.1. It does accept lambda functions (with the -std=c++0x option), such as:
auto lam = [=](int j) -> int {
printf("testing for lambdas: %d\t%d\n", n, j);
return n;
};
int g = lam(7);
The version of gcc installed at work is 4.1.2, so I'm guessing that the standard library is old?
/bin/libc.so.6
says it's version 2.5 compiled with gcc 4.1.2.
Is there a way around this?
thanks in advance for any help
I get the same behavior with icc 11.1 on a system where gcc 4.5.2 is installed.
g++'s header <functional> is protected with #ifdef __GXX_EXPERIMENTAL_CXX0X__ which is not defined when icc is used.
I would consider switching to boost::function in this setup, which of course works with icc.
Well, the code shown doesn't include a single header. And yet you refer to the standard library std::function.
So no, it doesn't compile. As with any other part of the standard library, you need to include the header where std::function is defined: <functional>.