469,311 Members | 2,483 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,311 developers. It's quick & easy.

iso c++ forbids decleration with no type

I have the following program:

#include "Vector.cpp"


#include <iostream>
using namespace std;

template<class Arg1, class Arg2, class Result>
struct binary_function
{
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};

template <class Type> class Average : std::binary_function<Type, Type, Type>

{
public:
result_type operator() (first_argument_type a, second_argument_type b)
{ return (a+b)*0.5;}
};

However, it gives me the following error:

ISO C++ forbids declaration of `result_type' with no type

About line

result_type operator() (first_argument_type a, second_argument_type b)

Replacing this line with

typename result_type operator() (first_argument_type a, second_argument_type b)

did not solve the problem.
Jul 12 '07 #1
20 12336
weaknessforcats
9,208 Expert Mod 8TB
You do not include .cpp files:
#include "Vector.cpp"
You add .cpp files to the build. You only inlude header files.

Header files may contain only declarations. That is, they contain nothing that will allocate memory. If they do, that is a definition and all definitions belong in a .cpp files.
Jul 12 '07 #2
Is this a rule? Because I have not been following this rule at all and did not run into any problems. Also, I don't think that this is going to solve my probem. My problem is related to

template<class Arg1, class Arg2, class Result> struct binary_function
{
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};

Somehow, the compiler is not processing what is inside the braces before it gets to

result_type operator() (first_argument_type a, second_argument_type b)

And, hence I am getting ISO C++ forbids declaration of `result_type' with no type error.

I am still in need of a solution to this
Jul 13 '07 #3
Darryl
86
The compiler isn't smart enough to realize that when you wrote result_type, you really meant binary_function<Type,Type, Type>::result_type, so be kind and tell it.
Jul 13 '07 #4
Although nothing prevents you from including C files (or any other file) its not usually done. The problem is, lets say you have my_a.c and my_b.c files that both intclude Vector.c. They will both compile fine but when they get linked togather you have every line of code duplicated in the binary and the link will fail. Same is true if you try to put functions in the header file (you only declare them not define them in the header).

So general rule is header files for types and function declarations and then the c file for the definitions. Then just include the header in your file and link in both C files during the compiling/linking.

Now for the problem you are seeing, Darryl has it right. 'result_type' is unknown, its in the namespace of binary_function structure so it needs that to qualify it. This is done because technically result_type could change based on your template arguements. In you case it does not but it could so each version of your template will have its very own result_type. If you want this more generic, just move it outside the binary_function struct on its own.
Jul 14 '07 #5
OK, I have tried a number of things based on your suggestions:

if I write

binary_function<Type,Type, Type>::result_type operator() (first_argument_type a, second_argument_type b)

I get the following error:
ISO C++ forbids declaration of `binary_function' with no type

If i write

std::binary_function<Type,Type, Type>::result_type operator() (first_argument_type a, second_argument_type b)

I get the following error:
expected `;' before "operator"

I have also tried:

typename std::binary_function<Type,Type, Type>::result_type operator() (first_argument_type a, second_argument_type b)

I get the following error:
declaration of `operator()' as non-function
Jul 14 '07 #6
Benny also, about your post#5. Are you suggesting suppose that in a project I have the following files:

matrix.h
matrix.cpp
vector.h
vector.cpp
main.cpp

So, I should include vector.h and matrix.h in main.cpp. And include, matrix.cpp in matrix.h and vector.cpp in vector.h. I think I am not getting this right. I would appreciate if you can clarify this. Thanks.
Jul 14 '07 #7
I have the following program:

#include "Vector.cpp"


#include <iostream>
using namespace std;

template<class Arg1, class Arg2, class Result>
struct binary_function
{
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};

template <class Type> class Average : std::binary_function<Type, Type, Type>

{
public:
result_type operator() (first_argument_type a, second_argument_type b)
{ return (a+b)*0.5;}
};

However, it gives me the following error:

ISO C++ forbids declaration of `result_type' with no type

About line

result_type operator() (first_argument_type a, second_argument_type b)

Replacing this line with

typename result_type operator() (first_argument_type a, second_argument_type b)

did not solve the problem.
You realize that you have your template class Average inheriting from std::binary_function (which doesn't exist) instead the one you defined? try taking the std:: from the 15th line in your original post.

After doing this (and removing that statement that includes a .cpp file) this builds fine.
Jul 14 '07 #8
I do not know what compiler you are using but removing that std actually creates errors in my program. I get all of the below errors about line 15:

expected template-name before '<' token

expected `{' before '<' token

expected unqualified-id before '<' token

expected `;' before '<' token

I kind of understand what you mean though. So you are saying this binary_function template I created above is not being reached when I write std::binary_function<Type, Type, Type>. You may be right, but removing std gives me even more new errors. So I am still puzzled about this.
Jul 15 '07 #9
Darryl
86
you need to add typename so it knows that's a type. Here is the code I got to compile.


Expand|Select|Wrap|Line Numbers
  1. template<class Arg1, class Arg2, class Result>
  2. struct binary_function
  3. {
  4.      typedef Arg1 first_argument_type;
  5.      typedef Arg2 second_argument_type;
  6.      typedef Result result_type;
  7. };
  8.  
  9. template <class Type> class Average : binary_function<Type, Type, Type>
  10. {
  11. public:
  12.      typename binary_function<Type, Type, Type>::result_type operator() (first_argument_type a, second_argument_type b)
  13.      { 
  14.           return (a+b)*0.5;
  15.      }
  16. };
  17.  
  18. int main()
  19. {
  20. }
  21.  
Jul 15 '07 #10
Darryl,

I don't know which compiler you are using, but when I try what you do in DEV C++. I get the following errors for line 9:

expected template-name before '<' token

expected `{' before '<' token

expected unqualified-id before '<' token

expected `;' before '<' token
Jul 15 '07 #11
Darryl,

I don't know which compiler you are using, but when I try what you do in DEV C++. I get the following errors for line 9:

expected template-name before '<' token

expected `{' before '<' token

expected unqualified-id before '<' token

expected `;' before '<' token
My code was virtually identical to Darryl's, except I had a return statement in my main. I don't know about him, but I use MS VS2005. And it worked fine.

I got the following code to compile and run, and give the correct results.
Also, I changed the * 0.5 in your binary function to / 2 otherwise it throws a warning if you use type int.

Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. template<class Arg1, class Arg2, class Result>
  5. struct binary_function
  6. {
  7.     typedef Arg1 first_argument_type;
  8.     typedef Arg2 second_argument_type;
  9.     typedef Result result_type;
  10. };
  11.  
  12. template <class Type>
  13. class Average : binary_function<Type, Type, Type>
  14. {
  15. public:
  16.     result_type operator() (first_argument_type a, second_argument_type b)
  17.     {
  18.         return (a+b) / 2;
  19.     }
  20. };
  21.  
  22. int main()
  23. {
  24.     Average<int> myAverage;
  25.     int x, y;
  26.  
  27.     cout << "Enter a number: ";
  28.     cin >> x;
  29.     cout << "Enter another number: ";
  30.     cin >> y;
  31.  
  32.     cout << "The average = " << myAverage(x, y) << endl;
  33.  
  34.     return 0;
  35. }
This works perfectly fine. And from before you can't put std::binary_functin, because binary_function is not defined in the std namespace.

It just occured to me. In your class average template all you use the same Type for result_type, first_argument_type, and second_argument_type. So why try to use those typedefs?

This works just as well.
Expand|Select|Wrap|Line Numbers
  1. template <class Type>
  2. class Average : binary_function<Type, Type, Type>
  3. {
  4. public:
  5.     Type operator() (Type a, Type b)
  6.     {
  7.         return (a+b) / 2;
  8.     }
  9. };
I don't see the reason for your typedefs in the binary_function struct. No matter how you inherit, you'll be able to just use the Type parameter passed to the binary_function struct. In fact, your binary_function struct doesn't really serve a purpose at all.

Expand|Select|Wrap|Line Numbers
  1. template <class Type>
  2. class Average
  3. {
  4. public:
  5.     Type operator() (Type a, Type b)
  6.     {
  7.         return (a+b) / 2;
  8.     }
  9. };
works just fine by itself.
Jul 15 '07 #12
weaknessforcats
9,208 Expert Mod 8TB
Benny also, about your post#5. Are you suggesting suppose that in a project I have the following files:

matrix.h
matrix.cpp
vector.h
vector.cpp
main.cpp

So, I should include vector.h and matrix.h in main.cpp. And include, matrix.cpp in matrix.h and vector.cpp in vector.h. I think I am not getting this right. I would appreciate if you can clarify this. Thanks.
No, you are not getting this right.

If main.cpp uses vector, then #include vector.h
If main.cpp uses matrix, then #include matrix.h
If vector.cpp uses vector, then #include vector.h
If maxtrix.cpp uses matrix, then #include matrix.h

You never #include .cpp files!!

Instead, you have multiple .cpp files in your project. Read about how a build works in a C++ textbook.

Second, I compiled your template as modifed by Darryl in Post #10 using Visual Studio.NET 2005 and it compiles fine. So my question is what compiler are you using?

Third, there already is a template named binary_function in the C++ standard header <functional>. Yours hides it and thereby will scrogg your STL at some point. You need to put stuff in a namespace and stop creating functions in the global namespace. That's why the std namespace was created in the first place: to avoid name collsions with functions already created as global functions:
Expand|Select|Wrap|Line Numbers
  1. #include <functional>
  2. using namespace std;
  3. int main()
  4. {
  5.     binary_function<int,int,int> fx;
  6. }
  7.  
  8.  
Jul 15 '07 #13
Phiefer3,

I agree with your last suggestion. It works without error in DEV C++ as well. Thanks for that. However, I have a question about this.

I am not the original author of this code, but I was wondering if writing

template <class Type> class Average

{
public:
Type operator() (Type a, Type b)
{ return (a+b)*0.5;}
};

is the same thing as writing Average as an extension of binary_function?
What exactly are we losing in terms of generality compared to the previous code? Is, this Average a function object (functor)?
Jul 15 '07 #14
I am using DEV c++ and I find it is giving me errors where most of the other compilers are not. Do you guys now any other free/low cost compilers that are more robust to small implementation differences?
Jul 15 '07 #15
weaknessforcats
9,208 Expert Mod 8TB
I am not the original author of this code, but I was wondering if writing

template <class Type> class Average

{
public:
Type operator() (Type a, Type b)
{ return (a+b)*0.5;}
};

is the same thing as writing Average as an extension of binary_function?
What exactly are we losing in terms of generality compared to the previous code? Is, this Average a function object (functor)?
Yes, the class Average is a functor since it implements the function operator: operator(). That is, you can use the object like a function:
Expand|Select|Wrap|Line Numbers
  1. Average<double>  obj;
  2. doube avg = obj(3.0, 4.0);   //functor: obj used as a function
  3.  
The STL binary_function is a base class for creating adaptable functors. You might read up on these. STL algorithms use adaptable functors heavily.

In STL-speak, an binary function is a function (or functor) that takes two arguments of type T and returns a type T.

A binary function that returns a bool is called a binary predicate.

Do not confuse binary function (a concept) with binary_function (a class).

Any STL code that calls for a binary function can use an object of your Average class.

Since there already is a binary_function in the std namespace, you should put your binary_function in your own namespace. Otherwise, you will get bit.
Assume you include your binary_function (all goes well) but if your don't and you also happen to use the <functional> header your code will use the std::binary_function. Now you can't tell which binary_function the compiler grabbed.

Since you can't know the names of the members of a namespace, you have to put your stuff in your own namespace in the assumption that you can keep track of yourself.
Jul 15 '07 #16
Phiefer3,

I agree with your last suggestion. It works without error in DEV C++ as well. Thanks for that. However, I have a question about this.

I am not the original author of this code, but I was wondering if writing

template <class Type> class Average

{
public:
Type operator() (Type a, Type b)
{ return (a+b)*0.5;}
};

is the same thing as writing Average as an extension of binary_function?
What exactly are we losing in terms of generality compared to the previous code? Is, this Average a function object (functor)?
The uninherited version works exactly the same as the version that inherits from that binary_function struct. I'm not even sure what use that struct would EVER be. all it does is create aliases for the datatypes that are passed to the template, you can just use those datatypes directly. So if this was another class template inheriting from binary_function this:
Expand|Select|Wrap|Line Numbers
  1. template <class Type1, class Type2, class Type3> 
  2. class otherClass : public binary_function<Type1, Type2, Type3>
  3. {
  4. public:
  5.     Type1 a;
  6.     Type2 b;
  7.     Type3 c;
  8. };
is exactly the same as this:
Expand|Select|Wrap|Line Numbers
  1. template <class Type1, class Type2, class Type3> 
  2. class otherClass : public binary_function<Type1, Type2, Type3>
  3. {
  4. public:
  5.     first_argument_type a;
  6.     second_argument_type b;
  7.     result_type c;
  8. };
Both simply declare public member variables of the types used as template parameters. But with the second, you need to remember what the names of the typedefs are and what order they're in.

Also, your original code may not have worked because you forgot the member access specifier when you inherited: class Average : public binary_function<Type, Type, Type>
Jul 15 '07 #17
weaknessforcats
9,208 Expert Mod 8TB
Both simply declare public member variables of the types used as template parameters. But with the second, you need to remember what the names of the typedefs are and what order they're in.
Yes, STL ask that you use the typedefs first_argument_type, result_type, value_type, etc.

Otherwise, no one else can read your STL code without analyzing it from scratch. I know what a first_argument_type is but I do not know what a Type1 is. Multiply this by the 100,000 developers who are TSDN members and you have STL template goulash.

The uninherited version works exactly the same as the version that inherits from that binary_function struct. I'm not even sure what use that struct would EVER be. all it does is create aliases for the datatypes that are passed to the template,
Read "Effective STL" by Scott Meyers Item #40. I didn't want to type the 5 pages here.


Again, I say that unless you derive from std::binary_function, your functor will not be adaptable. That is, it will not work with binder1st and binder2nd. As in,it won't compile.
Jul 15 '07 #18
Darryl
86
I missed a lot in today, you guys have been busy...

anyway in the mean time I downloaded Dev-c++ ( I normally use vs2005)

Anyway I got the original code to work by adding typename and full class name also to the parameters

Expand|Select|Wrap|Line Numbers
  1. template<class Arg1, class Arg2, class Result>
  2. struct binary_function
  3. {
  4.      typedef Arg1 first_argument_type;
  5.      typedef Arg2 second_argument_type;
  6.      typedef Result result_type;
  7. };
  8.  
  9. template <class Type> 
  10. class Average : binary_function<Type, Type, Type>
  11. {
  12. public:
  13.      typename binary_function<Type, Type, Type>::result_type operator() (typename binary_function<Type, Type, Type>::first_argument_type a, typename binary_function<Type, Type, Type>::second_argument_type b)
  14.      { 
  15.           return (a+b)*0.5;
  16.      }
  17. };
  18.  
  19. int main()
  20. {
  21. }
  22.  
Jul 16 '07 #19
Darryl
86
I missed a lot in today, you guys have been busy...

anyway in the mean time I downloaded Dev-c++ ( I normally use vs2005)

Anyway I got the original code to work by adding typename and full class name also to the parameters

Expand|Select|Wrap|Line Numbers
  1. template<class Arg1, class Arg2, class Result>
  2. struct binary_function
  3. {
  4.      typedef Arg1 first_argument_type;
  5.      typedef Arg2 second_argument_type;
  6.      typedef Result result_type;
  7. };
  8.  
  9. template <class Type> 
  10. class Average : binary_function<Type, Type, Type>
  11. {
  12. public:
  13.      typename binary_function<Type, Type, Type>::result_type operator() (typename binary_function<Type, Type, Type>::first_argument_type a, typename binary_function<Type, Type, Type>::second_argument_type b)
  14.      { 
  15.           return (a+b)*0.5;
  16.      }
  17. };
  18.  
  19. int main()
  20. {
  21. }
  22.  
*edit*

You can pick Visual C++ express for free. If you plan on doing any windows development, you'll have to also get the Platform SDK
Jul 16 '07 #20
thanks everyone, this was very helpful and informative...
Jul 16 '07 #21

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

17 posts views Thread by Tapeesh | last post: by
reply views Thread by Husam | last post: by
10 posts views Thread by sam_cit | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by suresh191 | last post: by
1 post views Thread by Geralt96 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.