Error with type alias - c++

I would like to use a type alias to create a template with one argument, from a template with two arguments:
// forward declaration
template<int Id, typename MixtureManager> class MixtureBridge;
/**
* Specialization of the MixtureTraits for the Gaussian_sjk_ model
**/
template<>
struct BridgeTraits<STK::Clust::Gaussian_sjk_>
{
// ... some traits
};
template <typename MixtureManager>
using GaussianBridge_sjk_m = MixtureBridge<STK::Clust::Gaussian_sjk_, MixtureManager>;
I get the following error message:
mixt_GaussianBridges.h:65:1: error: expected unqualified-id before 'using'
What is wrong with my syntax ?
Note: I am working with gcc 4.6.3, on Windows

Template aliases are not supported in gcc 4.6 : https://gcc.gnu.org/gcc-4.6/cxx0x_status.html
upgrade your compiler to a more recent version.

Alias-declarations are only supported from gcc 4.7 onwards
https://gcc.gnu.org/gcc-4.7/changes.html

Related

Why does the compiler issue a template recursion error?

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.

How to specify template deduction guides for template aliases?

I am trying to make this code compile in VS 2019 (16.10.4) with /std:c++17. The following fails:
namespace my
{
template<class _Key, class _Compare = std::less<_Key>, class _Allocator = std::allocator<_Key>>
using Set = std::set<_Key, _Compare, _Allocator>;
}
void test()
{
std::set set1 = { 1, 2, 3 };
static_assert(std::is_same_v<std::set<int>, decltype(set1)>);
my::Set set2 = { 1, 2, 3 }; // Error here.
static_assert(std::is_same_v<my::Set<int>, decltype(set2)>);
}
with error:
error C2955: 'my::Set': use of alias template requires template argument list
message : see declaration of 'my::Set'
The same code compiles fine on godbolt with gcc -std=c++17 without any deduction guides. See sample.
Is there a way to make this compile on VS 2019 (16.10.4) with /std:c++17? My actual code is quite verbose. I created this minimal reproducible sample and it might just come down to solving this small piece. I also tried specifying deduction guides for my::Set but they have similar errors.
my::Set in your code is an alias template, and class template argument deduction for alias templates is a new feature of C++20: https://en.cppreference.com/w/cpp/compiler_support/20
Experimentally one can find that template argument deduction in this example is available in Visual Studio since version 16.11, please also specify /std:c++20 command-line option. Demo: https://gcc.godbolt.org/z/93jdvfPcn
The same code compiles fine on godbolt with gcc -std=c++17 without any deduction guides.
It is a bug in GCC that it allows class template argument deduction for alias templates in C++17 mode: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103852

Fail to compile program using boost::spirit with Intel C++ compiler

I'm trying to compile the following example http://www.boost.org/doc/libs/1_60_0/libs/spirit/example/qi/compiler_tutorial/calc3.cpp using Intel C++ compiler.
Compilation fails and I get 300 kB of errors. The first few are:
boost/fusion/container/vector/vector.hpp(69): error: namespace "boost::fusion::vector_detail::result_of" has no member "value_at_c"
: boost::is_convertible<Sequence, typename result_of::value_at_c<This, 0>::type>
^
boost/fusion/container/vector/vector.hpp(69): error: expected a ">"
: boost::is_convertible<Sequence, typename result_of::value_at_c<This, 0>::type>
^
boost/fusion/container/vector/vector.hpp(69): error: not a class or struct name
: boost::is_convertible<Sequence, typename result_of::value_at_c<This, 0>::type>
^
Command line is
icl.exe /I<path-to-boost> calc3.cpp
Boost version: 1.60, compiler version: 15.0.6.285 Build 20151119
Although I was able to fix the error by changing the line 69
struct is_convertible_to_first
: boost::is_convertible<Sequence, typename result_of::value_at_c<This, 0>::type>
{};
to
struct is_convertible_to_first
: boost::is_convertible<Sequence, typename boost::fusion::result_of::value_at_c<This, 0>::type>
{};
,
I'm still curious why is there a problem?
The most reasonable guess is that the result_of namespace that ICC finds within boost::fusion::vector_detail is only a workaround for non-conforming compilers (e.g. I think GCC 4.6 lacks some support there too) so, the name clash with boost::fusion::result_of only manifests there.
So it's a bug reportable with the library devs; the namespace should be qualified more to accomodate old compilers. (It's possible it won't be fixed anymore if said compilers aren't supported)

MSVC pointer type attributes

I recently ran into a compilation warning (promoted to error) using the 64-bit VS2013 compiler (update 3) making me aware of the existence of pointer type attributes.
The warning indicated a loss of precision as I was about to assign something of type 'Object *' to 'Object * __ptr32'.
I didn't hear about this '__ptr32' suffix yet, so I did some googling and found the following link: http://blog.aaronballman.com/2013/05/msvc-pointer-type-attributes/ .
After reading this, it became clear that I shouldn't simply ignore this warning as I might get ugly bugs in my 64-bit application...
Trying to pinpoint the problem further, I wrote following small program:
#include <type_traits>
struct O { };
struct OD { using V = O *; };
template <typename X, typename Y> struct expect_equal { static_assert(std::is_same<X, Y>::value, "Types do not correspond."); };
template <class D> using VD = typename D::V;
template <class D> struct Exp { template <template <class> class T> using DT = T<D>; };
int main(void)
{
expect_equal<Exp<OD>::DT<VD>, O *> e;
return 0;
}
While it would compile using clang, I got the following error/assertion failure using my MSVC 64-bit compiler (note: the 32-bit compiler did not yield compilation errors):
Microsoft (R) C/C++ Optimizing Compiler Version 18.00.30723 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
test.cpp
test.cpp(6) : error C2338: Types do not correspond.
test.cpp(13) : see reference to class template instantiation 'expect_equal<O * __ptr32,O *>' being compiled
I was wondering whether someone could indicate what I am doing wrong here: I don't use an explicit pointer type attribute anywhere. This also might be a an unspecified behavior or a bug of either the STL implementation or the compiler, but most likely I am missing some important point here... Thanks in advance!

Unable to compile nsgmls with template erros

I am a avid emacs user, and want to use sgml markup check routine.
I was naturally headed towards nsgmls, and downloded the source code to compile it.
However, there was a strange error coming from the compiler with the followings.
./../include/RangeMap.h:57: error: type ‘Vector<RangeMapRange<From, To> >’ is not deri ved from type ‘RangeMapIter<From, To>’
./../include/RangeMap.h:57: error: expected ‘;’ before ‘ptr_’
./../include/RangeMap.h: In member function ‘Boolean RangeMapIter<From, To>::next(From&, From&, To&)’:
./../include/RangeMap.h:47: error: ‘ptr_’ was not declared in this scope
I know that some times compiler gets disgruntled by template and typename madness, however the codes seems to have already used typename correctly within the code.
Here are the cope snippets that arouses these errors.
template<class From, class To>
class RangeMapIter {
public:
RangeMapIter(const RangeMap<From,To> &map);
Boolean next(From &fromMin, From &fromMax, To &toMin) {
if (!count_)
return 0;
else {
fromMin = ptr_->fromMin;
fromMax = ptr_->fromMax;
toMin = ptr_->toMin;
ptr_++;
count_--;
return 1;
}
}
private:
size_t count_;
typename Vector<RangeMapRange<From,To> >::const_iterator ptr_;
};
Can anybody help me hash out those errors?
This error message is given by GCC in the wrong order of both type names. (but it apparently fixed this in the latest version). It is meant to say that Vector<RangeMapRange<From,To> >::const_iterator was not found to be a type name. The underlying cause of this diagnostic is that the code is parsed as an access-declaration, which has the following syntax
::[opt] nested-name-specifier template[opt] unqualified-id ;
An example of that syntax
struct A {
int a;
};
struct B : A {
// equivalent to: using A::a;
A::a;
};
In C++11 this access-declaration construct was taken out of the specification and it was deprecated in C++03. But since the compiler still supports parsing it, when the Vector<RangeMapRange<From,To> >::const_iterator is not found to be a type, it will be taken as a name to be declared in an access-declaration (so the parser moves forward across the type specifier section). Hence according to the above syntax, after the unqualified-id which in this case is const_iterator (and in my example was a), it wants to see a semicolon and it wants that Vector<RangeMapRange<From, To> > is a base class of RangeMapIter<From, To>, but confusingly the diagnostic it gives has it the other way around.
Check your names and make sure the type exists.