template <class T>
void trace(LogBuffer& msgBuffer, T& data)
{
data.trace(msgBuffer);
}

In the above template fuction we are using a generic class T, but when we are compiling on gcc4.1.3 compiler we ar getting the following error.

error:request for member 'trace' in 'data', which is of non-class type 'std::ios_base& ()(std::ios_base&)

The trace function is being called in some other file as shown below

template <class T>
LogBuffer& LogBuffer::operator<<(T & data)
{
trace(*this, data); // trace fuction called here
return *this;
}

We found that the above piece of code compiles fine on older version of gcc compiler like 2.9.


//Trace functions. These are the trace functions called form here we able to call different trace functions of different classes (due to the template deceleration)
//Again these trace functions are at different class of different files.
// here past compiler simply forget the problem of generic type. But GCC 4.1.2 compiler very much specific about this generic types.
// I hope that u can understand with this info..

this is the class which we have

class LogBuffer
{
public:

LogBuffer(LogFactor& logFactor);
~LogBuffer();

uint8_t* GetStart();
size_t GetProcessedSize();

void Flush();
void SetFormat(ios::fmtflags flags, ios::fmtflags mask);
uint8_t GetIndent();
void SetIndent(uint8_t indent);



// Generic flat type
template <class T>
LogBuffer& operator<<(T& data);

// Single element pointer
template <class T>
LogBuffer& operator<<(T* & data);

// Array
template <class T>
LogBuffer& operator<<(const MsgBufferArray<T>& data);


protected:
void SetDefaultFormat();

LoggerFunctor& _functor;
ostringstream _buffer;
uint8_t _indent;
};

and also that some of the definitions at different file are available in the frm of class members.
This template function is unable to resolve the type.

any suggestions....
|

Recommended Answers

All 5 Replies

I tried to remake the program and provide examples in an attempt to reproduce the problem on Microsoft Visual C++ 2005/2008 compiler, but I different errors than the one I expected despite the tests--

Similar Problem here

/**
 * Assumed header file for LogBuffer
 */
#ifndef LOGBUFFER_H
#define LOGBUFFER_H

#include <iostream>

/* Dummy values */
typedef char LogFactor;
typedef int uint8_t;
template<class T>class MsgBufferArray;
typedef char LoggerFunctor;
typedef char ostringstream;

using std::ios;

namespace Log{
	
	class LogBuffer;

	template <class T>
	void trace(LogBuffer& msgBuffer, T& data);

	class LogBuffer{

		public:
			LogBuffer(LogFactor& logFactor);
			~LogBuffer();

			uint8_t* GetStart();
			size_t GetProcessedSize();

			void Flush();
			void SetFormat(ios::fmtflags flags, ios::fmtflags mask);
			uint8_t GetIndent();
			void SetIndent(uint8_t indent);


			// Generic flat type
			template <class T>
			LogBuffer& operator<<(T& data);

			// Single element pointer
			template <class T>
			LogBuffer& operator<<(T* & data);

			// Array
			template <class T>
			LogBuffer& operator<<(const MsgBufferArray<T>& data);


		protected:
			void SetDefaultFormat();

			//LoggerFunctor& _functor;
			ostringstream _buffer;
			uint8_t _indent;
	};


}

#include "LogBuffer.cpp"

#endif
/**
 * Assumed implementation file of LogBuffer
 */
#ifdef LOGBUFFER_H

using namespace Log;

LogBuffer::LogBuffer(LogFactor& logFactor){}

LogBuffer::~LogBuffer(){}

template <class T>
LogBuffer& LogBuffer::operator<<(T & data){

	::trace(*this, data); // trace fuction called here
	return *this;
}

template <class T>
void trace(LogBuffer& msgBuffer, T& data){

	data.trace(msgBuffer);
}

#endif
/**
 * Driver program for testing--
 */
#include <iostream>
#include "LogBuffer.h"

using std::cout;
using std::cin;
using std::endl;

class Tracer{
	public:
		Tracer(){}
		void trace(LogBuffer& msgBuffer){
			cout << "Trace successful" << endl;
		}
};

class NonTracer{

	public:
		NonTracer(){}
		char trace;
};


int main(){
	
	char refChar = '\0';	// dummy variable
	Tracer myTracer;	// object of type Tracer, has the method trace
	NonTracer myNonTracer;	// object of type NonTracer, doesn't have trace function but a trace mbmer
	Tracer myOtherTracer(); // pointer to a function that accepts no arguments and returns a Tracer
	LogBuffer lb (refChar);	// making a LogBuffer object and passing it the dummy variable

	lb << myTracer;	// works
	// lb << myNonTracer;	// obviously doesn't work, but doesn't reproduce desired error
	// lb << myOtherTracer; Error	1	error C2228: left of '.trace' must have class/struct/union	h:\visual studio 2008\projects\testingtemplates__\testingtemplates__\tesitngtemplate__t.cpp	35	TestingTemplates__
	// myOtherTracer.trace(LogBuffer(refChar)); Error	1	error C2228: left of '.trace' must have class/struct/union	h:\visual studio 2008\projects\testingtemplates__\testingtemplates__\tesitngtemplate__t.cpp	35	TestingTemplates__

	cin.ignore();
	cin.get();
	return 0;
}

Perhaps the errors differ from compiler to compiler, or it may be possible that the examples provided above were not adjacent to the example in the link?

The error seems to occur in gcc (and/or g++?) type compilers so I think the error stated above may be the same thing though I can't confirm it without experience with those compilers.

this is my mini project of testing the code at different compilers I am a learner of testing. My master starts with this task. but he also struck with this point.

Now I clearly explain the scenario.

compiling fib_msg.cpp . It is including header files like fib_msg.h, hf_logger.h, hf_looger_impl.h and hf_list.h . I have taken preprocessor output for fib_msg.cpp. I found that all the files r included one after another.
step 1. In fib_msg.h

#include "hf_logger.h"
#include "hf_list.h
inline
void trace(HF_OLogBuffer& msgBuffer, fib_msg_reqHeader_t& data) 
{
    msgBuffer << "cbHandle=0x";
    msgBuffer << hex << setw(8) << setfill('0') << data.cbHandle << endl; // [B]error : instantiated from here [/B]
    msgBuffer << "cbCorrelator=0x";
    msgBuffer << hex << setw(8) << setfill('0') << data.cbCorrelator << endl; 
    msgBuffer << "errorReporting=";
    msgBuffer << fib_trace_value(g_fib_trace_errorReportingTypes,
                                 data.errorReporting,
                                 "unknown type");
    msgBuffer << endl;
    msgBuffer << "msgSubId=" << data.msgSubId << endl;          
}

step 2. first is the hf_logger.h where u can see the function call on a definition of overloading operator function.

class LogBuffer
{
public:

    LogBuffer(LoggerFunctor& loggerFunctor);
    ~LogBuffer();
    uint8_t*     GetStart(); 
    size_t       GetProcessedSize();
    void        Flush();
    void        SetFormat(ios::fmtflags flags, ios::fmtflags mask); 
    uint8_t     GetIndent();
    void        SetIndent(uint8_t indent);
   // Basic types
    LogBuffer& operator<<(int8_t&   data);       // a character, not a number
    LogBuffer& operator<<(const int8_t&   data); // a character, not a number
    LogBuffer& operator<<(uint8_t&  data);       // a character, not a number
    LogBuffer& operator<<(const uint8_t&  data); // a character, not a number
        // C strings
    LogBuffer& operator<<(const char* data);
    LogBuffer& operator<<(char data[]);      
    // std::string
    LogBuffer& operator<<(std::string& data);
    LogBuffer& operator<<(const std::string& data);
    
    [B]// Generic flat type this function is current issue generator  
    template <class T>
    LogBuffer& operator<<(T& data);[/B]
    
    // Single element pointer
    template <class T>
    LogBuffer& operator<<(T* & data);
    // Array
    template <class T>
    LogBuffer& operator<<(const MsgBufferArray<T>& data); 
    // Manipulators
    LogBuffer& operator<<(ios& (*fct)(ios& iosArg));
};
[B]template <class T>
void trace(HF_OLogBuffer& msgBuffer, T& data)  
{
    data.trace(msgBuffer);
}// this is the function call from which we got an error i.e. {request for member 'trace' in 'data', which is of non-class type 'std::ios_base& ()(std::ios_base&)'}
[/B]
inline
void trace(HF_OLogBuffer& msgBuffer, HF_int8_t& data) 
{
    msgBuffer << data;
}//and so on trace functions definitions..

step 3. then we have hf_logger_impl.h

template <class T>
inline
HF_OLogBuffer& HF_OLogBuffer::operator<<(T& data)
{
    trace(*this, data);//  [B]error: instantiated from 'HF_OLogBuffer& HF_OLogBuffer::operator<<(T&) [with T = std::ios_base& ()(std::ios_base&)]'[/B]
    return *this;
}

step 4. Finally with hf_list.h

#include "hf_logger.h"

template <class T, class Alloc=BufferChunkAllocator>
class MsgBufferList
{
public:
    MsgBufferList(Alloc& alloc) {init(alloc);} 
    void init(Alloc& alloc)
    {
        _n         = 0;
        _first     = 0;
        _last      = 0;
        _allocator = &alloc;
    }
    uint32_t size() {return _n;}
       
        
   [B] void trace(HF_OLogBuffer& msgBuffer)
    {
        MsgBufferListElem<T>* elemP = _first;

        for (NPF_uint32_t i = 0; (i < _n) && elemP; i++)
        {
            msgBuffer << elemP;
            elemP = elemP->_next;
        }
    }[/B]

    uint32_t              _n;
    MsgBufferListElem<T>* _first;
    MsgBufferListElem<T>* _last;
};

// So now U can understand.

I think the problem may exist in your hf_logger.h file--

class LogBuffer
{
public:

    LogBuffer(LoggerFunctor& loggerFunctor);
    ~LogBuffer();
    uint8_t*     GetStart(); 
    size_t       GetProcessedSize();
    void        Flush();
    void        SetFormat(ios::fmtflags flags, ios::fmtflags mask); 
    uint8_t     GetIndent();
    void        SetIndent(uint8_t indent);
   // Basic types
    LogBuffer& operator<<(int8_t&   data);       // a character, not a number
    LogBuffer& operator<<(const int8_t&   data); // a character, not a number
    LogBuffer& operator<<(uint8_t&  data);       // a character, not a number
    LogBuffer& operator<<(const uint8_t&  data); // a character, not a number
        // C strings
    LogBuffer& operator<<(const char* data);
    LogBuffer& operator<<(char data[]);      
    // std::string
    LogBuffer& operator<<(std::string& data);
    LogBuffer& operator<<(const std::string& data);
    
    // Generic flat type this function is current issue generator  
    template <class T>
    LogBuffer& operator<<(T& data);
    
    // Single element pointer
    template <class T>
    LogBuffer& operator<<(T* & data);
    // Array
    template <class T>
    LogBuffer& operator<<(const MsgBufferArray<T>& data); 
    // Manipulators

    // Takes a pointer to an ios that accepts an ios arg, ios_base
    LogBuffer& operator<<(ios& (*fct)(ios& iosArg));
};
template <class T>
void trace(HF_OLogBuffer& msgBuffer, T& data)  
{
    data.trace(msgBuffer);
}// this is the function call from which we got an error i.e. {request for member 'trace' in 'data', which is of non-class type 'std::ios_base& ()(std::ios_base&)'}

inline
void trace(HF_OLogBuffer& msgBuffer, HF_int8_t& data) 
{
    msgBuffer << data;
}//and so on trace functions definitions..

Because you only have a 'specialization' for an ios type (and anything derived from it) and not its super type, you're generalized function is invoked instead of the one you most likely intended to be invoked.

That's my assumption, given the error generated. I only know so much about call-backs, but if what I'm thinking is true your member in fib_msg_reqHeader_t cbHandle is a pointer to a function that takes an ios_base reference and returns an ios_base reference and since you don't have a specialization for your callback the generic type is being called.

You could probably resolve the error by allowing your overloaded<< definition that takes a pointer to a function that accepts and returns an ios reference to instead allow pointers to a function that accepts and returns an ios_base.

I think the problem may exist in your hf_logger.h file--

class LogBuffer
{
public:

    LogBuffer(LoggerFunctor& loggerFunctor);
    ~LogBuffer();
    uint8_t*     GetStart(); 
    size_t       GetProcessedSize();
    void        Flush();
    void        SetFormat(ios::fmtflags flags, ios::fmtflags mask); 
    uint8_t     GetIndent();
    void        SetIndent(uint8_t indent);
   // Basic types
    LogBuffer& operator<<(int8_t&   data);       // a character, not a number
    LogBuffer& operator<<(const int8_t&   data); // a character, not a number
    LogBuffer& operator<<(uint8_t&  data);       // a character, not a number
    LogBuffer& operator<<(const uint8_t&  data); // a character, not a number
        // C strings
    LogBuffer& operator<<(const char* data);
    LogBuffer& operator<<(char data[]);      
    // std::string
    LogBuffer& operator<<(std::string& data);
    LogBuffer& operator<<(const std::string& data);
    
    // Generic flat type this function is current issue generator  
    template <class T>
    LogBuffer& operator<<(T& data);
    
    // Single element pointer
    template <class T>
    LogBuffer& operator<<(T* & data);
    // Array
    template <class T>
    LogBuffer& operator<<(const MsgBufferArray<T>& data); 
    // Manipulators

    // Takes a pointer to an ios that accepts an ios arg, ios_base
    LogBuffer& operator<<(ios& (*fct)(ios& iosArg));
};
template <class T>
void trace(HF_OLogBuffer& msgBuffer, T& data)  
{
    data.trace(msgBuffer);
}// this is the function call from which we got an error i.e. {request for member 'trace' in 'data', which is of non-class type 'std::ios_base& ()(std::ios_base&)'}

inline
void trace(HF_OLogBuffer& msgBuffer, HF_int8_t& data) 
{
    msgBuffer << data;
}//and so on trace functions definitions..

Because you only have a 'specialization' for an ios type (and anything derived from it) and not its super type, you're generalized function is invoked instead of the one you most likely intended to be invoked.

That's my assumption, given the error generated. I only know so much about call-backs, but if what I'm thinking is true your member in fib_msg_reqHeader_t cbHandle is a pointer to a function that takes an ios_base reference and returns an ios_base reference and since you don't have a specialization for your callback the generic type is being called.

You could probably resolve the error by allowing your overloaded<< definition that takes a pointer to a function that accepts and returns an ios reference to instead allow pointers to a function that accepts and returns an ios_base.

I am very thankful to ur reply. But I didnt get U. error at some other line but u mentioned another line i.e ios_base. Could u please check it once and please give me the reply.

error: this is the function call from which we got an error i.e. {request for member 'trace' in 'data', which is of non-class type 'std::ios_base& ()(std::ios_base&)'}

What I'm saying is change the operator prototype--

// Takes a pointer to an ios that accepts an ios arg, ios_base
    LogBuffer& operator<<(ios& (*fct)(ios& iosArg));

-- and definition to --

// Takes a pointer to an ios that accepts an ios arg, ios_base
    LogBuffer& operator<<(ios_base& (*fct)(ios_base& iosArg));

--but only if the operations within the operator will allow you to do so. Since ios_base is a super-type of ios I'm assuming that ios_base wont have the same functionality (or the same amount of members) as ios.

In the event that you do not want to change the definition of your operator for ios-types, change your cbHandle to accept and return a reference to an ios type instead of an ios_base.

/**
 * Possible definition of fib_msg_reqHeader_t before you decide to change it
 */
struct fib_msg_reqHeader_t{
    //...
    
    ios_base& (*cbHandle)(ios_base&);

    //...

};
/**
 * Possible definition of fib_msg_reqHeader_t after you decide to change it
 */
struct fib_msg_reqHeader_t{
    //...
    
    ios& (*cbHandle)(ios&);

    //...

};

--again only do this if it wont make any major changes in other portions of code. Consider each option carefully and if you find a solution you can simply add another stream-extraction operator to handle ios_base types.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.