I use gcc 4.7.3 for ARM platform to compile my code. I have several classes like this:
// types.h
enum Types
{
kType1,
kType2
// ...
};
// d1.h
class D1 : public Base
{
public:
static const int type = kType1;
// ...
};
// d2.h
class D2 : public Base
{
public:
static const int type = kType2;
// ...
};
Somewhere in the sources I use those classes:
MyObject obj;
doSomething<D1>(obj);
doSomething<D2>(obj);
// other.cpp
class Foo
{
template<typename T>
void doSomething(MyObject obj)
{
mm_.insert(std::multimap<int, MyObject>::value_type(T::type, obj));
}
};
And get the next messages (during linking):
undefined reference to `D1::kType`
undefined reference to `D2::kType`
// more messages of this type
OK. If I change do_something function like this:
template<typename T>
void doSomething(MyObject obj)
{
mm_.insert(std::multimap<int, MyObject>::value_type( (int) T::type, obj));
}
it compiles OK. But why? Can't find anything in the standard about it. Does anybody have ideas about what's going on?
Thanks.
P.S.
This fix
// d1.cpp
const int D1::kType;
also works, but this is expected.
P.P.S. the answer would be quite obvious in case of using reference or pointer to T::type, but I don't see anything that requires a ref or ptr. AFAIK std::multimap::value_type take the arguments by value (not ref, nor ptr).
// d1.cpp
const int D1::kType;
// d2.cpp
const int D2::kType;
is the answer,
//d1.h
public:
static const int type = kType1;
Is like a function prototype, it is compiled into every complication object (cpp file) that includes the header, and so because of the ODR rule it doesn't actually reserve the memory space, or else the linker would find lots of instances of the variable in every compilation unit which included the header.
You therefore need one compilation unit (a cpp file) which defines the actual memory space that will be used for the class constant found in the header that is used multiple times.
Related
I would like to understand why compiler does not figure out private struct in public function. For example:
class List
{
public:
List();
List(const List&);
bool remove(int);
bool insert(int, ItemType );
Node *find(int);
void toString();
ItemType retrive(int);
int getSize();
private:
struct Node
{
ItemType item;
Node *next;
};
int size;
Node *head;
};
In this code, which is portion of a Linked List header, gnu compiler gives me this error:
error: unknown type name 'Node'
Node *find(int);
I found a topic related with this issue but I do not understand why it works.
Setting a private struct as a return value.
In C++ every name used, such as Node, must have been previously declared, i.e. earlier in the source code. There is an exception for the bodies of member functions. You can think of this exception as a textual transformation that's applied before the compilation proper, where the function /definitions/, if any, are moved to a point after the class definition, with only a declaration left in the class. Thus a reference to Node in a function body would be OK (treated as if it was after that hypothetical transformation). But not in the return value specification.
This means that you can address the issue by reordering your class definition:
class List
{
struct Node
{
ItemType item;
Node *next;
};
int size;
Node *head;
public:
List();
List(const List&);
bool remove(int);
bool insert(int, ItemType );
Node *find(int);
void toString();
ItemType retrive(int);
int getSize();
};
Although many relate C++ as an object oriented programming language; that is only but a small subset of the language core. This paradigm can get some people into trouble because C++ at its roots just like C is a procedural programming language.
Consider this snippet of code:
#include <iostream>
#include <string>
int main() {
std::string hello("hello");
std::string world("world");
std::string helloWorld = getConcatString( hello, world );
std::cout << helloWorld << std::endl;
return 0;
}
std::string getConcatString( const std::string& str1, const std::string& str2 ) {
return str1 + std::string(" ") + str2;
}
The above will not compile, this will fail when it reaches the 8th line in this code. This fails for the same reason as it does in your class. The compiler comes across getConcatString(...) yet it is not declared nor defined before hand as C++ is a procedural language at its core. This is why you need a forward declaration before a function, struct, class, etc. is used. The compiler needs to know how much memory to set aside and needs to know what type of memory it is going to allocate either it be local, dynamic, static, const etc. Everything in C++ happens in a sequence of order.
To fix the above code you have two options:
Define the function, class, struct etc. before they are used.
Or Have a function prototype, or class forward declaration that is before its use.
When it comes to a class's structure I typically follow this pattern:
class ClassName /*struct StructName*/ {
public:
// variables, constants, enums, structs, unions, typedefs here
protected:
// variables, enums, structs, unions, typedefs here if using inheritance
private:
// variables, enums, structs, unions, typedefs here to encapsulate
public:
// Constructors & Destructor if being declared here.
// public functions or methods, setters & getters here.
protected:
// Constructor - Copy Constructor if Abstract - Inheriting.
// protected methods for inheriting classes.
private:
// Constructor - If fully preventing from creating an instance of this class or if the class is fully static.
// private methods that are specific to this class.
}; // ClassName /*struct StructName*/
This way if there are any internal structs or classes within a class or struct it helps to prevent the problem that you are having.
EDIT
I would also like to add that if a class contains an object and manages it's resource with dynamic memory on the heap via pointer then it is better to have a forward declaration of that class in the containing class's header file, then include the resource's header file in the containing class's cpp file as such:
Foo.h
#ifndef FOO_H
#define FOO_H
class Bar; // forward declaration
class Foo {
private:
Bar* bar_; // For demonstration purposes I'm using a raw pointer...
// It is wiser to use smart pointers.
public:
Foo( /*properties to create an instance of Bar*/ );
~Foo(); // Destructor Implemented see Rule of 3, 4 or 5...
// Copy Construct & overloaded operator=() needed here
...
// other public functions
}; // Foo
#endif // FOO_H
Foo.cpp
#include "Foo.h";
#include "Bar.h";
Foo::Foo( /* properties need for Foo & to properly create Bar on the heap*/ ) {
// Allocation of Bar Here
}
Foo::~Foo() {
// deallocation of Bar here.
}
Other wise if Foo is using bar as a local internal instance, copy or reference that is local to Foo and is independent of Bar meaning that Bar does not include Foo or have any access to Foo's internals then it is safe to just include Bar's header in Foo's Header as such:
Foo.h
#ifndef FOO_H
#define FOO_H
#include "Bar.h"
class Foo {
private:
Bar bar_; // local stack copy
public:
Foo(){} // Default - Empty Class
// Any of these constructors would be okay
explicit Foo( Bar bar );
explicit Foo( Bar& bar );
explicit Foo( const Bar bar );
explicit Foo( const Bar& bar );
}; // Foo
#endif // FOO_H
Foo.cpp
#include "Foo.h"
// Do not need to include Bar.h
// Constructors here.
This pertains to the use of forward declarations but it is also tied into the prevention of circular includes.
In C++ language the contexts that can "look ahead" and see the entire class definition are limited to: member function bodies, default arguments, exception specifications and in-class non-static data member initializers.
I.e. for the above reason the following example is legal†
struct S
{
void foo(void *p = (N *) 0) throw(N)
{
N n;
}
unsigned s = sizeof(N);
struct N {};
};
even though it uses name N above (i.e. before) its point of declaration.
In your example you are attempting to use a yet-undeclared name Node in a function return type. Function return type does not belong to the above list. So, this is not allowed in C++. Declare Node before using it in function return types.
† GCC refuses to compile the exception specification throw(N), while Clang is perfectly happy with it. Maybe it has something to do with deprecation of this language feature.
I have a bunch of things mixed, and they all lead to undefined references. Please, excuse me for simply dropping the code, but, since I don't know which are the individual problems, I can't search for them.
c.hpp
// A public class
class C {
private:
// This class is private because it is used just for convenience;
// it is not part of C's interface. Its methods are not defined because
// the types for which it will be instantiated are known.
template<typename T>
class Base {
private:
T* variable;
public:
// Note that this method should be available to C users, i.e., it
// is part of the interface. Should Base then be in the public
// section of C?
T* get() const noexcept;
};
public:
// Users of this class do not care how Derived1 and Derived2 are
// implemented. Since they were very similar in nature (think of
// them as the various iterator versions), I decided that it would
// be better to let the shared code be in a common template which
// was then instantiated for a set of known parameters.
class Derived1 : public Base<char> {
public:
int function() noexcept;
};
class Derived2 : public Base<int> {
/* ... */
};
};
// Should the following be included? Would it avoid unneeded implicit instantiations,
// or are those already avoided because C::Base's methods are declared but not defined?
extern template C::Base<char>;
extern template C::Base<int>;
c.cpp
template<typename T>
T* C::Base<T>::get() const noexcept {
return this->variable;
}
// This approach serves to hide the implementation and to shorten build times,
// while maintaining the flexibility of templates. Or so I believe.
template class C::Base<char>;
template class C::Base<int>;
// This should be another question, but... is this the correct place for
// class method attributes? There isn't much information about attributes.
[[gnu::visibility("default")]]
int C::Derived1::function() noexcept {
return 7;
}
When the code is compiled under default visibility, it all compiles, links and runs fine. However, if visibility is switched to hidden, which is what I want to achieve, there are linking errors:
undefined reference to C::Base<char>::get() const
undefined reference to C::Base<int>::get() const
The rest of the code links fine, because all functions are marked with the appropiate visibility attribute, as shown. Since the public functions of C::Base are intended to be part of the exposed interface, they should be marked with default visibility too, but I don't know how. For instance, all of the following seems to be forbidden:
// This is not possible because templates are not "real" entities
[[gnu::visibility("default")]]
template<typename T>
T* C::Base<T>::get() const noexcept {
return this->variable;
}
// But it isn't possible to specify it here either!
[[ /*error*/ ]] template [[ /*error*/ ]] class [[ /*error*/ ]]
C::Base<int> [[ /*error*/ ]];
I have also tried to specify the attribute in the declaration of the methods:
class C {
private:
template<typename T>
class Base {
private:
/* ... */
public:
[[gnu::visibility("default")]]
T* get() const noexcept;
};
/* ... */
};
but it didn't change anything.
Could you please explain what is happening, covering the concerns expressed in the comments? Specifically, how and where should the visibility attribute be specified?
I'm trying to build a solution which has three files. With main.cpp it is four files.
Entity.h
#pragma once
#include "SystemBase.h"
namespace Engine {
class Entity {
public:
Entity() { }
void s(SystemBase* sb) { }
};
}
SubscribersList.h
#pragma once
#include "SystemBase.h"
#include "Entity.h"
namespace Engine {
class SubscribersList {
friend SystemBase;
public:
SubscribersList() { }
void f(Entity* e) { }
};
}
SystemBase.h
#pragma once
#include "SubscribersList.h"
#include "Entity.h"
namespace Engine {
class SystemBase {
public:
SystemBase() { }
void g(Entity* e) { }
private:
SubscribersList m;
};
}
Don't focus on the body's of methods in the headers. It is just to keep things simple. I found two ways to build the solution.
1. Write the word class before all class names. But it crashes when I try to separate the realization from prototypes.
2. Write all code in one file.
I don't/won't write the keyword class before all class names to build the solution, and certainly I don't/won't write a big project in one file. So why I can't build it? What is the magic?!
To understand the problem of cyclic header dependency we first need understand the difference between a class declaration and definition and the concept of incomplete types.
A prototype or forward declaration of a type Type is written as:
class Type;
Such a forward declaration allows you to create pointers and reference to that type.
You cannot however instantiate, dereference pointers to or use a reference to Type until its full type is declared.
A declaration for Type could be written as:
class AnotherType;
class Type {
public:
void aMemberFunc();
private:
AnotherType *m_theOtherThing;
};
Now we have the declaration instances can be created and pointers to Type can be dereferenced.
However before m_theOtherThing is dereferenced or instanciated AnotherType must be fully declared.
class AnotherType {
Type m_aType;
}
Should do, which gives us both the full declaration and definition of AnotherType.
That allows to continue on to write the definition of Type::aMemberFunc:
void Type::aMemberFunc() {
m_theOtherThing = new AnotherType();
}
If instead of presenting this code to the compiler in this order we instead presented the full declarations of Type and AnotherType up front:
class Type {
public:
void aMemberFunc();
private:
AnotherType *m_theOtherThing;
};
class AnotherType {
Type m_aType;
}
Then AnotherType *m_theOtherThing; will fail to compile as AnotherType has not been declared or forward declared by that point.
Switching the order gives:
class AnotherType {
Type m_aType;
}
class Type {
public:
void aMemberFunc();
private:
AnotherType *m_theOtherThing;
};
Now Type m_aType; will not compile as Type has not been declared. A forward declaration would not do in this case.
Using #pragma once instead of header guards does not in anyway change the problem. #pragma once only ensures the header is include just once it does not effect the order the compiler processes the code otherwise. It certainly does not allow the compiler to ignore undefined types when it reaches them.
For this kind of class structure there is no way for the compiler to be able to process it without the use for forward declarations.
Follow-up question to [Does casting to a pointer to a template instantiate that template?].
The question is just as the title says, with the rest of the question being constraints and usage examples of the class template, aswell as my tries to achieve the goal.
An important constraint: The user instantiates the template by subclassing my class template (and not through explicitly instantiating it like in my tries below). As such, it is important to me that, if possible, the user doesn't need to do any extra work. Just subclassing and it should work (the subclass actually registers itself in a dictionary already without the user doing anything other than subclassing an additional class template with CRTP and the subclass is never directly used by the user who created it). I am willing to accept answers where the user needs to do extra work however (like deriving from an additional base), if there really is no other way.
A code snippet to explain how the class template is going to be used:
// the class template in question
template<class Resource>
struct loader
{
typedef Resource res_type;
virtual res_type load(std::string const& path) const = 0;
virtual void unload(res_type const& res) const = 0;
};
template<class Resource, class Derived>
struct implement_loader
: loader<Resource>
, auto_register_in_dict<Derived>
{
};
template<class Resource>
Resource load(std::string const& path){
// error should be triggered here
check_loader_instantiated_with<Resource>();
// search through resource cache
// ...
// if not yet loaded, load from disk
// loader_dict is a mapping from strings (the file extension) to loader pointers
auto loader_dict = get_all_loaders_for<Resource>();
auto loader_it = loader_dict.find(get_extension(path))
if(loader_it != loader_dict.end())
return (*loader_it)->load(path);
// if not found, throw some exception saying that
// no loader for that specific file extension was found
}
// the above code comes from my library, the code below is from the user
struct some_loader
: the_lib::implement_loader<my_fancy_struct, some_loader>
{
// to be called during registration of the loader
static std::string extension(){ return "mfs"; }
// override the functions and load the resource
};
And now in tabular form:
User calls the_lib::load<my_fancy_struct> with a resource path
Inside the_lib::load<my_fancy_struct>, if the resource identified by the path isn't cached already, I load it from disk
The specific loader to be used in this case is created at startup time and saved in a dictionary
There is a dictionary for every resource type, and they map [file extension -> loader pointer]
If the dictionary is empty, the user either
didn't create a loader for that specific extension or
didn't create a loader for that specific resource
I only want the first case to have me throw a runtime exception
The second case should be detected at compile / link time, since it involves templates
Rationale: I'm heavily in favor of early errors and if possible I want to detect as many errors as possible before runtime, i.e. at compile and link time. Since checking if a loader for that resource exists would only involve templates, I hope it's possible to do this.
The goal in my tries: Trigger a linker error on the call to check_error<char>.
// invoke with -std=c++0x on Clang and GCC, MSVC10+ already does this implicitly
#include <type_traits>
// the second parameter is for overload resolution in the first test
// literal '0' converts to as well to 'void*' as to 'foo<T>*'
// but it converts better to 'int' than to 'long'
template<class T>
void check_error(void*, long = 0);
template<class T>
struct foo{
template<class U>
friend typename std::enable_if<
std::is_same<T,U>::value
>::type check_error(foo<T>*, int = 0){}
};
template struct foo<int>;
void test();
int main(){ test(); }
Given the above code, the following test definition does achieve the goal for MSVC, GCC 4.4.5 and GCC 4.5.1:
void test(){
check_error<int>(0, 0); // no linker error
check_error<char>(0, 0); // linker error for this call
}
However, it should not do that, as passing a null pointer does not trigger ADL. Why is ADL needed? Because the standard says so:
§7.3.1.2 [namespace.memdef] p3
[...] If a friend declaration in a nonlocal class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup or by qualified lookup until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship). [...]
Triggering ADL through a cast, as in the following definition of test, achieves the goal on Clang 3.1 and GCC 4.4.5, but GCC 4.5.1 already links fine, as does MSVC10:
void test(){
check_error<int>((foo<int>*)0);
check_error<char>((foo<char>*)0);
}
Sadly, GCC 4.5.1 and MSVC10 have the correct behaviour here, as discussed in the linked question and specifically this answer.
The compiler instatiates a template function whenever it is referenced and a full specification of the template is available. If none is available, the compiler doesn't and hopes that some other translation unit will instantiate it. The same is true for, say, the default constructor of your base class.
File header.h:
template<class T>
class Base
{
public:
Base();
};
#ifndef OMIT_CONSTR
template<class T>
Base<T>::Base() { }
#endif
File client.cc:
#include "header.h"
class MyClass : public Base<int>
{
};
int main()
{
MyClass a;
Base<double> b;
}
File check.cc:
#define OMIT_CONSTR
#include "header.h"
void checks()
{
Base<int> a;
Base<float> b;
}
Then:
$ g++ client.cc check.cc
/tmp/cc4X95rY.o: In function `checks()':
check.cc:(.text+0x1c): undefined reference to `Base<float>::Base()'
collect2: ld returned 1 exit status
EDIT:
(trying to apply this to the concrete example)
I'll call this file "loader.h":
template<class Resource>
struct loader{
typedef Resource res_type;
virtual res_type load(std::string const& path) const = 0;
virtual void unload(res_type const& res) const = 0;
loader();
};
template<class Resource>
class check_loader_instantiated_with : public loader<Resource> {
virtual Resource load(std::string const& path) const { throw 42; }
virtual void unload(Resource const& res) const { }
};
template<class Resource>
Resource load(std::string const& path){
// error should be triggered here
check_loader_instantiated_with<Resource> checker;
// ...
}
And another file, "loader_impl.h":
#include "loader.h"
template<class Resource>
loader<Resource>::loader() { }
This solution has one weak point that I know of. Each compilation unit has a choice of including either only loader.h or loader_impl.h. You can only define loaders in compilation units that include loader_impl, and in those compilation units, the error checking is disabled for all loaders.
After thinking a bit about your problem, I don't see any way to achieve this. You need a way to make the instantiation "export" something outside the template so that it can be accessed without referencing the instantiation. A friend function with ADL was a good idea, but unfortunately it was shown that for ADL to work, the template had to be instantiated. I tried to find another way to "export" something from the template, but failed to find one.
The usual solution to your problem is to have the user specializes a trait class:
template < typename Resource >
struct has_loader : boost::mpl::false_ {};
template <>
struct has_loader< my_fancy_struct > : boost::mpl::true_ {};
To hide this from the user, you could provide a macro:
#define LOADER( loaderName, resource ) \
template <> struct has_loader< resource > : boost::mpl::true_ {}; \
class loaderName \
: the_lib::loader< resource > \
, the_lib::auto_register_in_dict< loaderName >
LOADER( some_loader, my_fancy_struct )
{
public:
my_fancy_struct load( std::string const & path );
};
It is up to you to determine whether having this macro is acceptable or not.
template <class T>
class Wrapper {};
void CheckError(Wrapper<int> w);
template <class T>
class GenericCheckError
{
public:
GenericCheckError()
{
Wrapper<T> w;
CheckError(w);
}
};
int main()
{
GenericCheckError<int> g1; // this compiles fine
GenericCheckError<char> g2; // this causes a compiler error because Wrapper<char> != Wrapper<int>
return 0;
}
Edit:
Alright this is as close as I can get. If they subclass and either instantiate OR define a constructor that calls the parent's constructor, they will get a compiler error with the wrong type. Or if the child class is templatized and they subclass and instantiate with the wrong type, they will get a compiler error.
template <class T> class Wrapper {};
void CheckError(Wrapper<int> w) {}
template <class T>
class LimitedTemplateClass
{
public:
LimitedTemplateClass()
{
Wrapper<T> w;
CheckError(w);
}
};
// this causes no compiler error
class UserClass : LimitedTemplateClass<int>
{
UserClass() : LimitedTemplateClass<int>() {}
};
// this alone (no instantiation) causes a compiler error
class UserClass2 : LimitedTemplateClass<char>
{
UserClass2() : LimitedTemplateClass<char>() {}
};
// this causes no compiler error (until instantiation with wrong type)
template <class T>
class UserClass3 : LimitedTemplateClass<T>
{
};
int main()
{
UserClass u1; // this is fine
UserClass2 u2; // this obviously won't work because this one errors after subclass declaration
UserClass3<int> u3; // this is fine as it has the right type
UserClass3<char> u4; // this one throws a compiler error
return 0;
}
Obviously you can add other accepted types by defining additional CheckError functions with those types.
I have this class that has a static member. it is also a base class for several other classes in my program. Here's its header file:
#ifndef YARL_OBJECT_HPP
#define YARL_OBJECT_HPP
namespace yarlObject
{
class YarlObject
{
// Member Variables
private:
static int nextID; // keeps track of the next ID number to be used
int ID; // the identifier for a specific object
// Member Functions
public:
YarlObject(): ID(++nextID) {}
virtual ~YarlObject() {}
int getID() const {return ID;}
};
}
#endif
and here's its implementation file.
#include "YarlObject.hpp"
namespace yarlObject
{
int YarlObject::nextID = 0;
}
I'm using g++, and it returns three undefined reference to 'yarlObject::YarlObject::nextID linker errors. If I change the ++nextID phrase in the constructor to just nextID, then I only get one error, and if I change it to 1, then it links correctly. I imagine it's something simple, but what's going on?
Make sure you are linking against the generated .o file. Double-check the makefile.