User-defined compile-time warnings

I was wondering if there is a way to check if a function is called in main(), and if it is, have the compiler spit out a warning.

This prints a warning, but does so even if foo() is not actually called:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;

void foo() { 
   cout << "foo"
   #warning This code will print foo
}

int main() {
     // foo(); 
     // Here, it doesn't matter whether foo() is called, the warning still appears on compile

   return 0;
}


Is there a way to have a warning printed out only if a user tries to use a certain function?

Thanks...
No standard way. There might be compilers with special features supporting this but I don't know. What are you trying to do? Is foo deprecated?
I have a program with two constructors for a class.
One constructor (constructor_b, let's say) doesn't define an attribute, and it has to be defined later using a different function.
I want the compiler to warn users when they call constructor_b
I presume you are having problems because you cannot modify the constructors themselves?

Perhaps if you can show us the prototypes for the constructors (any class templates, inheritances, the function types for the constructors, etc) we may be able to show you some cheap trick...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <iostream>
#include <string>

/* Program to simulate flowcharts, adding console applications.
 Flowcharts are composed of cells, which are interconnected.
 Cells are either linked to other Cells by yes or no, or they
 do not have links. The former are called LinkCell, the later
 are PassCell. PassCells display a message, then the program
 either 'passes' to another Cell or exists.*/

using namespace std;

// Generic Cell class
class Cell {
protected:
    string msg;
public:
    string getMsg() { return msg; }
    virtual void flow() = 0;
};

// Linked Cell class
class LinkCell : public Cell {
private:
	string val;
	Cell* yLink;
	Cell* nLink;
public:
	LinkCell( const string& );
    LinkCell( const string&, Cell*, Cell* );
	void setVal();
	string getVal(){ return val; }
	void flow();
    void setLink(Cell*, Cell*);
    Cell* getyLink() { return yLink; }
    Cell* getnLink() { return nLink; }
};

LinkCell::LinkCell( const string& setMsg ) {
    this->msg = setMsg;
    #warning setting up to call LinkCell constructor call without links - make sure links are defined for object with setLink()
}

LinkCell::LinkCell ( const string& setMsg, Cell *yParam, Cell *nParam ) {
    this->msg = setMsg;
    this->yLink = yParam;
    this->nLink = nParam;
}

void LinkCell::setLink( Cell *yParam, Cell *nParam ){
    this->yLink = yParam;
    this->nLink = nParam;
}


void LinkCell::setVal() {
    cout << this->getMsg() << " [y/n] ";
    cin >> this->val;
    while (( this->getVal()!="y" ) && ( this->getVal()!="n" )){
        cout << "Please enter y or n: ";
        cin >> val;
    }
}

void LinkCell::flow(){
	setVal();
    if ( this->getVal()=="y" ) { this->yLink->flow(); }
    if ( this->getVal()=="n" ) { this->nLink->flow(); }
}

// EndCell class
class EndCell : public Cell {
public:
	EndCell( const string& );	
	void flow();
};

EndCell::EndCell ( const string& setMsg ) { 
	this->msg = setMsg;
}

void EndCell::flow() {
	cout << this->getMsg() << endl;
}

// PassCell class
class PassCell : public Cell {
	Cell *link;
public:
	PassCell( const string& );
    PassCell( const string&, Cell* );
	void flow();
    void setLink(Cell*);
    Cell* getLink() { return link; };
};

PassCell::PassCell ( const string& setMsg ) {
	this->msg = setMsg;
    #warning setting up to call PassCell constructor without link - make sure link is defined for object with setLink()
}

PassCell::PassCell ( const string& setMsg, Cell *param ) {
	this->msg = setMsg;
	this->link = param;
}

void PassCell::setLink(Cell * param) {
	this->link = param;
}

void PassCell::flow() {
	cout << this->getMsg() << endl;
	this->link->flow();
}
Way are you going for some complex design of the code .
composition and aggregation simultaneously . what is the point or is it possible ?
Last edited on
I see what you are doing.

You are wasting your time worrying about it. It is not your class's job to make sure that the user is using it properly. What you should do is make sure all your members are properly initialized, like so:

1
2
3
4
5
6
7
8
9
10
LinkCell::LinkCell( const string& setMsg ) {
    this->msg = setMsg;
    // Make sure that the links are properly invalid until the using code sets them with setLink()
    this->yLink = NULL;
    this->nLink = NULL;

    // Another option is to put an ASSERT here which will cause your program to barf while in debug mode (don't forget to #include <cassert>):
    assert( this->yLink != NULL );
    assert( this->nLink != NULL );
}

There is another option, but it is trickier to maintain: declare the derived default constructor as private or protected. You should be aware that this will have consequences with copy and move semantics -- but if you stick to properly dyamically-allocated heap objects (using pointers and new and delete for everything) then you should be alright.

Hope this helps.
@Duoas

Thanks! That really helped... I can't use assert though since that would imply that yLink/nLink are set before the constructor, when they should be able to be set after, using setLink().

However, I didn't quite get what
1
2
this->yLink = NULL;
this->nLink = NULL;

would do... could you please clarify?

Again, thanks a lot.
Without this->nLink = NULL;, nLink can/will be a random value, making it impossible to check whether it's properly initialized. By setting it to NULL (or simply 0), you can check at any later point whether they are properly set:
void someFct() { if (this->yLink) { // Execution code } }

I don't really see why you can't use assert. Not in the constructor, but in any code that requires the links to be set.
Oh, I understand now :-)
Thank you
Topic archived. No new replies allowed.