FC++ is a library for functional programming in C++. I am using it on MinGW with gcc 4.5.0. When I use the more basic features, I have no problems. But one of the more advanced features is giving me a template-related error (or maybe there's just a problem with my code...couldn't be!).
Does anybody have FC++ working with 4.5.0? See anything wrong with my code?
The link text is solidly out of date, though it shows a history of issues with gcc and template specialization. The link text isn't more up to date.
Here's my code:
#include <iostream>
#include "prelude.h"
using namespace fcpp;
using namespace std;
struct TwoTimes {
template <class T>
struct Sig : public FunType<T,T> {};
template <class F>
F operator() (const F& x) const { return 2*x; };
} twoTimes;
int main(int argc, char* argv[] )
{
cout << compose(twoTimes,twoTimes)(3) << endl;
return 0;
}
The error I get is:
In file included from full.h:14:0,
from lambda.h:38,
from operator.h:29,
from function.h:23,
from reuse.h:14,
from list.h:31,
from prelude.h:32,
from y.cxx:2:
smart.h: In instantiation of 'fcpp::FunctoidTraits<TwoTimes>':
prelude.h:142:74: instantiated from 'fcpp::impl::XCompose::Sig<TwoTimes, TwoTimes>'
full.h:94:53: instantiated from 'fcpp::Full2<fcpp::impl::XCompose>::Sig<TwoTimes, TwoTimes>'
y.cxx:18:46: instantiated from here
smart.h:103:7: error: no type named 'Type' in 'struct
fcpp::impl::NeededASmartFunctoidButInsteadGot<TwoTimes, false>'
In file included from y.cxx:2:0:
prelude.h: In instantiation of 'fcpp::impl::XCompose::Sig<TwoTimes, TwoTimes>':
full.h:94:53: instantiated from 'fcpp::Full2<fcpp::impl::XCompose>::Sig<TwoTimes, TwoTimes>'
y.cxx:18:46: instantiated from here
prelude.h:142:74: error: 'fcpp::FunctoidTraits<TwoTimes>::max_args' is not a valid
template argument for type 'int' because it is a non-constant expression
In file included from lambda.h:38:0,
from operator.h:29,
from function.h:23,
from reuse.h:14,
from list.h:31,
from prelude.h:32,
from y.cxx:2:
full.h: In instantiation of 'fcpp::Full2<fcpp::impl::XCompose>::Sig<TwoTimes, TwoTimes>':
y.cxx:18:46:
instantiated from here
full.h:94:53: error: no type named 'Arg1Type' in 'struct
fcpp::impl::XCompose::Sig<TwoTimes, TwoTimes>'
y.cxx: In function 'int main(int, char**)':
y.cxx:18:46: error: no match for call to '(fcpp::Compose) (TwoTimes&, TwoTimes&)'
Well .... the links you refer to are seven years old. In dog and compiler years, that is a good lifetime.
If you want functional programming with (current) C++ compilers, maybe some of the Boost libraries may be of interest?
If the answer is still needed to this, the struct TwoTimes needs to be wrapped to work with FC++. I have worked a lot with FC++ over several years. The best thing I can do is point to here on the C2 wiki where I have discussed this:
http://c2.com/cgi/wiki?FunctoidsInCpp
Any posting there I will see.
Related
I have a simple program containing the following code:
namespace nam
{
struct S{};
void f(S *){}
}
void f(nam::S *){}
int main()
{
nam::f(nullptr);
nam::S s;
f(&s);
return 0;
}
I expect that this will compile fine because I am calling f the second time without specifying namespace nam. However, upon compiling the code, I get this error:
$ g++ main.cpp -std=c++11 -Wall -Wextra
main.cpp: In function ‘int main()’:
main.cpp:14:9: error: call of overloaded ‘f(nam::S*)’ is ambiguous
f(&s);
^
main.cpp:7:6: note: candidate: void f(nam::S*)
void f(nam::S *){}
^
main.cpp:4:10: note: candidate: void nam::f(nam::S*)
void f(S *){}
Compiler and version:
$ gcc --version
gcc (Debian 5.3.1-14) 5.3.1 20160409
After trying this with different compilers, similar errors are returned. This seems to be a defined part of C++. I can't find anywhere on the internet where it says that calling a function with a struct in namespace nam as a parameter effectively implies using namespace nam; and requires ::f to remove ambiguity. I have 2 questions about this:
Where is this defined in the C++ standard?
Is there a good reason for this behavior?
Personally I like to avoid using namespace x; and similar. I want the compiler to give me an error when I don't specify a namespace. This behavior stops the compiler from doing so, and this means my code is inconsistent in places, because I occasionally forget to specify the namespace when calling functions like f that are not declared globally anywhere.
Your implementation of f(nam::S*) is outside of the namespace of 'nam'
change:
void f(nam::S *){}
to:
void nam::f(nam::S *){}
(or just move the enclosing namespace bracket) and all should be fine.
if your call to f(&s) in the current namespace was intentional then you need to specify this by changing the function call to
::f(&s)
As was said in the comments, this is due to argument-dependent lookup. I guess now I'll have to figure out now if I want to always specify the namespace in my code where this would make it unnecessary, or never specify it.
I'm writing a library code on top of Boost Geometry library. My class should be templated on the coordinate type (usually int/float/double etc.).
The code below (stripped down to bare minimum) doesn't compile and I get a compilation error that doesn't help me.
The code:
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
template <typename CoordType>
class MyClass {
public:
typedef boost::geometry::model::point<CoordType, 2, boost::geometry::cs::cartesian> MyPoint;
CoordType getX(const MyClass<CoordType>::MyPoint &p) const { return p.get<0>(); }
};
The error:
test.cpp: In member function 'CoordType MyClass<CoordType>::getX(const MyClass<CoordType>::MyPoint&) const':
test.cpp:8:82: error: expected primary-expression before ')' token
I'm compiling this code with: g++ -I./boost_1_54_0 test.cpp -o test.o. I used different versions of G++ 4.5.2/4.7.2/4.8.1, but I still get the same error.
What am I missing here?
Thanks in advance.
Using the free function boost::geometry::get<0>(p); recommended in the boost docs circumvents this problem.
I agree with the answer of us2012, using boost::geometry::get<0>() is recommended.
The actual problem was that the template keyword was missing, so this:
{ return p.template get<0>(); }
would have fixed the problem.
I am reading the chapter "function templates" of C++ Primer 3rd edition, and when I tried to follow the example, I found the code almost the same as the book has encountered an error during compilation under VC6 but everything is ok under g++. I don't know why?
Here is the code:
#include <iostream>
using namespace std;
template<typename T1, typename T2, typename T3>
T1 my_min(T2 a, T3 b)
{
return a>b?b:a;
}
int main()
{
int (*fp)(int, int) = &my_min<int>;
cout<<fp(3,5)<<endl;
return 0;
}
The error happened under VC6 appears like:
error C2440: 'initializing' : cannot convert from '' to 'int (__cdecl *)(int,int)'
None of the functions with this name in scope match the target type
VC6 is an ancient compiler whose support for templates is woefully lacking, so it cannot cope with legal code in many circumstances. You should ditch it and download VS 2010 Express instead.
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.
I am trying to understand how to best make use of blocks in my templated class.
I have the following code snippet:
template<typename T, typename R>
class MyClass {
public:
typedef R (^Block)(T);
MyClass(Block blk) {}
};
void testMyClass() {
MyClass<int,int>::Block blk(^(int arg) {
return 1 + arg;
});
}
When I try to compile this, I get the following error message:
error: cannot convert ‘int (^)(int)’ to ‘R (^)(T)’ in initialization
Am I missing something obvious? Am I trying to do something that is not allowed? GCC accepts the program if I do the same thing without templates.
This is an issue in GCC. I tested your program under LLVM 3 and it compiled just fine.
There are a number of problems in GCC 4.2's implementation of blocks, sometimes they can be worked around by fully qualifying your block declarations ^int(int arg){return 1 + arg;} but in this case it was unable to work around this issue. I would highly recommend moving to use LLVM/Clang for any further work with Obj-C Blocks. Its C++ support is very good these days, especially for C++03 support.