Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 3

Qt-interest Archive, March 2008
a question on Qt unit test


Message 1 in thread

Hi all

I'm doing unit test with Qt.  However,  I always get 'undefined reference to function XXX'  errors when compiling my test.cpp.

I figured out the erros are due to the fact function XXX is inlined.

So my question is what I am supposed to do to test inlined functions?


Thanks

Yifei

Message 2 in thread

On Monday 17 March 2008 18:59:58 Yifei Li wrote:
> Hi all
>
> I'm doing unit test with Qt.  However,  I always get 'undefined reference
> to function XXX'  errors when compiling my test.cpp.
>
> I figured out the erros are due to the fact function XXX is inlined.
>
> So my question is what I am supposed to do to test inlined functions?
>
undefined inlines? whut?
mind posting some code? and maybe the full error message.


-- 
 [ signature omitted ] 

Message 3 in thread

Thank you for the reply. For example, here's I've been trying to do:

/////// file: a.h ///////////
class A
{
inline double foo();
};

///// file: a.cpp ////////
#include "a.h"
double A::foo()
{
   double result;
   ...
    return result;
}


/////file: test.cpp/////
#include <QtTest/QtTest>
#include "a.h"

class TestA
{
private slots:
    void testfoo();
};

void TestA::testfoo()
{
     A obj;
    QCOMPARE(obj.foo(), expected_result);
}

-------------------------------------------
When I tried to compile test.cpp, I got :
test.cpp : undefined reference to 'TestA::foo()'

My pro file looks like:
CONFIG += qtestlib
TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .
HEADERS += a.h
SOURCES += a.cpp

----- Original Message ----- 
From: "Arvid Ephraim Picciani" <aep@xxxxxxxxxxxxxxx>
To: <qt-interest@xxxxxxxxxxxxx>
Sent: Monday, March 17, 2008 14:03
Subject: Re: a question on Qt unit test


> On Monday 17 March 2008 18:59:58 Yifei Li wrote:
>> Hi all
>>
>> I'm doing unit test with Qt.  However,  I always get 'undefined reference
>> to function XXX'  errors when compiling my test.cpp.
>>
>> I figured out the erros are due to the fact function XXX is inlined.
>>
>> So my question is what I am supposed to do to test inlined functions?
>>
> undefined inlines? whut?
> mind posting some code? and maybe the full error message.
>
>
> -- 
> best regards/Mit freundlichen GrÃÃen
> Arvid Ephraim Picciani
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with 
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
> 

--
 [ signature omitted ] 

Message 4 in thread

On Monday 17 March 2008 20:07:28 Yifei Li wrote:
> Thank you for the reply. For example, here's I've been trying to do:
>
> /////// file: a.h ///////////
> class A
> {
> inline double foo();
> };
>
> ///// file: a.cpp ////////
> double A::foo()
> {

you can't put inlines in body files. thats.... pointless. didnt even expect it 
to compile.



-- 
 [ signature omitted ] 

Message 5 in thread

On Monday 17 March 2008 20:11:24 Arvid Ephraim Picciani wrote:
> On Monday 17 March 2008 20:07:28 Yifei Li wrote:
> > Thank you for the reply. For example, here's I've been trying to do:
> >
> > /////// file: a.h ///////////
> > class A
> > {
> > inline double foo();
> > };
> >
> > ///// file: a.cpp ////////
> > double A::foo()
> > {
>
> you can't put inlines in body files. thats.... pointless. didnt even expect
> it to compile.
Yes you can.
This is C++, not of of those odd languages that force you to use naming 
conventions for files: you're free to do as you like.
If you wanted to you could call all your header files .cpp and all your 
implementation files .h
It would be a bit messy, and there are probably very few people who will 
appreciate it, but the compiler will not complain as long as you do it 
correctly and keep including your .cpp files ;-)

The inline keyword is best viewer as a compiler hint. The compiler is free to 
ignore is. You are also allowed to put an inline funtion in an implementation 
file, and if you do that, it's a pretty good bet that the function will never 
actually be inlined, but it will compile. 
Also, you will need to link against the implementation file in that case (for 
obvious reasons).

By the looks of it, the reason for the unresolved external is that the 
original poster did not link to a.o . Test.cpp is not part of the project: so 
qtestlib will build, but attempting to just build test.cpp requires linking 
to a.o manually.

Happy coding,
Eric

--
 [ signature omitted ] 

Message 6 in thread

On Monday 17 March 2008 23:09:11 Eric Methorst wrote:
> Yes you can. 
> This is C++, not of of those odd languages that force you to use naming
> conventions for files: you're free to do as you like.
> If you wanted to you could call all your header files .cpp and all your
> implementation files .h

> It would be a bit messy, and there are probably very few people who will
> appreciate it, but the compiler will not complain as long as you do it
> correctly and keep including your .cpp files ;-)
>
> The inline keyword is best viewer as a compiler hint. The compiler is free
> to ignore is. You are also allowed to put an inline funtion in an
> implementation file, and if you do that, it's a pretty good bet that the
> function will never actually be inlined, but it will compile.
> Also, you will need to link against the implementation file in that case
> (for obvious reasons).

Yay. basic C++ lesson!
where do i have to click to run my C++  script now?

> By the looks of it, the reason for the unresolved external is that the
> original poster did not link to a.o . Test.cpp is not part of the project:
> so qtestlib will build, but attempting to just build test.cpp requires
> linking to a.o manually.

just bad that you are darn right. i just tested his code and it compiles. 
weird.  I'd actually expect gcc to complain about not beeing able to inline 
at all. Propably it just ignores it anyway. *shrug*. gcc bugs coders way to 
less about useless code.
-- 
 [ signature omitted ] 

Message 7 in thread

Eric Methorst wrote:
>By the looks of it, the reason for the unresolved external is that the
>original poster did not link to a.o . Test.cpp is not part of the
> project: so qtestlib will build, but attempting to just build test.cpp
> requires linking to a.o manually.

While that is a strong possibility, the compiler is free not to emit the 
function at all if it is marked inline.

If it's not marked inline and it's declared in a separate header, the 
compiler will think twice about removing the function definition because 
it might be called from other .cpp files or even from another library 
entirely. In other words, the compiler cannot remove an out-of-line copy 
of a symbol with external linkage if it's not explicitly marked as 
inline.

However, if it's marked as inline, the compiler may choose to completely 
inline it and remove the out-of-line definition. Other .cpp files and 
other libraries will get an unresolved symbol in that case. (The compiler 
may also ignore the inline keyword)

This is not theory, it's actual scenario. I've seen this happen.

-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.


Message 8 in thread

On Tuesday 18 March 2008 00:48:03 Thiago Macieira wrote:
> Eric Methorst wrote:
> >By the looks of it, the reason for the unresolved external is that the
> >original poster did not link to a.o . Test.cpp is not part of the
> > project: so qtestlib will build, but attempting to just build test.cpp
> > requires linking to a.o manually.
>
> While that is a strong possibility, the compiler is free not to emit the
> function at all if it is marked inline.
>
> If it's not marked inline and it's declared in a separate header, the
> compiler will think twice about removing the function definition because
> it might be called from other .cpp files or even from another library
> entirely. In other words, the compiler cannot remove an out-of-line copy
> of a symbol with external linkage if it's not explicitly marked as
> inline.
>
> However, if it's marked as inline, the compiler may choose to completely
> inline it and remove the out-of-line definition. Other .cpp files and
> other libraries will get an unresolved symbol in that case. (The compiler
> may also ignore the inline keyword)
Been there, done that, got the T-shirt ;-)
>
> This is not theory, it's actual scenario. I've seen this happen.


--
 [ signature omitted ] 

Message 9 in thread

Quoting Eric Methorst <arnalon@xxxxxxxxx>:

> On Monday 17 March 2008 20:11:24 Arvid Ephraim Picciani wrote:
> > On Monday 17 March 2008 20:07:28 Yifei Li wrote:
> > > Thank you for the reply. For example, here's I've been trying to do:
> > >
> > > /////// file: a.h ///////////
> > > class A
> > > {
> > > inline double foo();
> > > };
> > >
> > > ///// file: a.cpp ////////
> > > double A::foo()
> > > {
> >
> > you can't put inlines in body files. thats.... pointless. didnt even expect
> > it to compile.
> Yes you can.
> This is C++, not of of those odd languages that force you to use naming
> conventions for files: you're free to do as you like.

Sorry to burst your bubble, but you are flat out wrong.

The last sentence of para 3, chapter 3 "Basic concepts", section 2 "One
definition rule" of the C++ standard says

"An inline function shall be defined in every translation unit in which it is
used."

For debug builds, there's a good chance that defining a inline function once in
an implementation file will work, as many compilers do no inlining for debug
builds. It also might work for large functions that aren't inlined in optimized
builds as well. I'd also expect it to work if the functions are only called from
the implementation file, and not from any other translation unit. In any other
case, I would expect "unresolved external" errors at link time. And given the
rule above from the standard, the code is wrong and the link editor is right.

A+
Paul

--
 [ signature omitted ] 

Message 10 in thread

On Tuesday 18 March 2008 16:02:51 Paul Floyd wrote:
> Quoting Eric Methorst <arnalon@xxxxxxxxx>:
> > On Monday 17 March 2008 20:11:24 Arvid Ephraim Picciani wrote:
> > > On Monday 17 March 2008 20:07:28 Yifei Li wrote:
> > > > Thank you for the reply. For example, here's I've been trying to do:
> > > >
> > > > /////// file: a.h ///////////
> > > > class A
> > > > {
> > > > inline double foo();
> > > > };
> > > >
> > > > ///// file: a.cpp ////////
> > > > double A::foo()
> > > > {
> > >
> > > you can't put inlines in body files. thats.... pointless. didnt even
> > > expect it to compile.
> >
> > Yes you can.
> > This is C++, not of of those odd languages that force you to use naming
> > conventions for files: you're free to do as you like.
>
> Sorry to burst your bubble, but you are flat out wrong.
Sorry to burst your bubble, but no I'm not.
>
> The last sentence of para 3, chapter 3 "Basic concepts", section 2 "One
> definition rule" of the C++ standard says
>
> "An inline function shall be defined in every translation unit in which it
> is used."
That is a misinterpretation of the specs on your part.

There's two ways of finding a function: 
1) providing it compile time (classic inline function in a header file)
2) providing it at link time (regular functions)

If I define an inline function in a cpp file, it will compile for my class. 
Any other class that wants to use this function must have it defined.
thus 
"An inline function shall be defined in every translation unit in which it is 
used." 
is not an instruction to the compiler but to the *user* (=You the programmer)!

In other words, if I define my inline function in a.cpp then if I want to use 
it in class b (b.cpp) I will need to:
---- file b.cpp ----
#include "b.h"
#include "a.cpp"

unless either b.cpp contains nothing else or only other inline functions (in 
which case you'd better call it b_ext.h or something) this is never going to 
compile because you will have multiple definitions for B's other (regular) 
functions.

The rationale for this is quite simple: this is programming, not magic.
There is no way, that the compiler can ever possibly know what the definition 
of your inline function is unless you include it. So treating that sentence 
as an instruction to the compiler cannot be done because the compiler can 
never know where the original definition *IS*.
Is the compiler supposed to go through every file in every directory in your 
path and or include path and or -I <path>'s and look in every file present to 
see if there's a definition for my inline B function?  Should it scan all my 
disks? connect to the internet? Google it???
Compiler output:
"unresolved external inline B::foo(). Should I yahoo it? (yes/no)"
Forgive the sarcasm, but he C++ spec is a little ambiguous. 
My rule of thumb: it's a computer, not magic ;-) 

At best, you might read this line as an instruction to the linker. But then, 
there would be no difference between an inline function and a regular one 
wouldn't there?


>
> For debug builds, there's a good chance that defining a inline function
> once in an implementation file will work, as many compilers do no inlining
> for debug builds. It also might work for large functions that aren't
> inlined in optimized builds as well. I'd also expect it to work if the
> functions are only called from the implementation file, and not from any
> other translation unit. In any other case, I would expect "unresolved
> external" errors at link time. And given the rule above from the standard,
> the code is wrong and the link editor is right.
>
> A+
> Paul
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body. List archive and information:
> http://lists.trolltech.com/qt-interest/


--
 [ signature omitted ] 

Message 11 in thread

Quoting Eric Methorst <arnalon@xxxxxxxxx>:
> On Tuesday 18 March 2008 16:02:51 Paul Floyd wrote:

> > Sorry to burst your bubble, but you are flat out wrong.
> Sorry to burst your bubble, but no I'm not.

You are still wrong.

> > The last sentence of para 3, chapter 3 "Basic concepts", section 2 "One
> > definition rule" of the C++ standard says
> >
> > "An inline function shall be defined in every translation unit in which it
> > is used."
> That is a misinterpretation of the specs on your part.

No. You do understand what is meant by "translation unit", I hope.

> There's two ways of finding a function:
> 1) providing it compile time (classic inline function in a header file)
> 2) providing it at link time (regular functions)

There are more than that.

> If I define an inline function in a cpp file, it will compile for my class.
> Any other class that wants to use this function must have it defined.
> thus
> "An inline function shall be defined in every translation unit in which it is
> used."
> is not an instruction to the compiler but to the *user* (=You the
> programmer)!

Are you really claiming that the C++ standard does not provide instructions as
to how compilers should behave? Specifically, that the ODR is only for
programmers, not for compilers?

> In other words, if I define my inline function in a.cpp then if I want to use
> it in class b (b.cpp) I will need to:
> ---- file b.cpp ----
> #include "b.h"
> #include "a.cpp"
>
> unless either b.cpp contains nothing else or only other inline functions (in
> which case you'd better call it b_ext.h or something) this is never going to
> compile because you will have multiple definitions for B's other (regular)
> functions.

More precisely this will only work if a.cpp contains nothing with external
linkage, assuming it is included more than once.

What is your point? Conventionally, implementation files do not include other
implementation files. Of course doing so is not illegal.

Why not just do the simple, conventional thing and put your inlines with the
declarations? That way experienced programmers will understand it, and the
compiler and linker will compile and link it.

[snip fatuous remarks]

> At best, you might read this line as an instruction to the linker. But then,
> there would be no difference between an inline function and a regular one
> wouldn't there?

It is clear to me that you do not understand the meaning of the inline keyword.
There is always a difference between an inline function and a non-inline one.

I suggest that you read the "Basic concepts" chapter of the C++ standard, and
think about what the compiler does when it does not emit inline code for an
inline function. And think a bit harder about your claim that "The inline
keyword is best viewed as a compiler hint. The compiler is free to ignore it."

A+
Paul
-- 
 [ signature omitted ] 

Message 12 in thread

/////// file: a.h ///////////
class A
{
inline double foo();
};

///// file: a.cpp ////////
#include "a.h"
double A::foo()
{
   double result;
   ...
    return result;
}

Above is your code. It should be changed to

/////// file: a.h ///////////
class A
{
    double foo()
	{
		double result;
		...
		return result;
	};
};



--
 [ signature omitted ] 

Message 13 in thread

Yifei Li wrote:
>class A
>{
>inline double foo();
>};

What's the point of making it inline if you don't give the body of the 
function?

Don't add "inline" unless you're also implementing the function.

-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.


Message 14 in thread

On Monday 17 March 2008 18:59:58 Yifei Li wrote:
> Hi all
>
> I'm doing unit test with Qt.  However,  I always get 'undefined reference
> to function XXX'  errors when compiling my test.cpp.
>
> I figured out the erros are due to the fact function XXX is inlined.
>
> So my question is what I am supposed to do to test inlined functions?

Can you show a sample code?

-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.