Re: Circular Class Template Friendship
From: Victor Bazarov (v.Abazarov_at_comAcast.net)
Date: 07/24/04
- Next message: Rob Williscroft: "Re: Circular Class Template Friendship"
- Previous message: Jeremie: "Static variables and threads"
- In reply to: Thomas Matthews: "Circular Class Template Friendship"
- Next in thread: Rob Williscroft: "Re: Circular Class Template Friendship"
- Reply: Rob Williscroft: "Re: Circular Class Template Friendship"
- Reply: Thomas Matthews: "Re: Circular Class Template Friendship"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Sat, 24 Jul 2004 16:59:19 GMT
"Thomas Matthews" <Thomas_MatthewsSpamBotsSuck@sbcglobal.net> wrote...
> I am converting my table and record classes into templates.
> My issue is the syntax of declaring a friend class within
> the template. I have searched the C++ FAQ Lite (web),
> the C++ newsgroups, "Thinking In C++" to no avail.
>
>
> Background
> ----------
> My table is a collection of <integer, string> pairs, in
> which the string is a fixed width that is specialized.
> One specialization of the table may have a 32 length
> string and another 64. The table is also a Singleton.
>
> The record class is of the form <integer, string>.
> The integer portion, the primary key, is hidden from
> public usage, so that the class behaves like a string.
> When the class is written as a field of a record, the
> integer portion will be written out.
>
> Part of the interface is for the table to be a friend
> of the record. This allows the table to set the primary
> key without giving access or knowledge of the primary
> key to the general public.
>
>
> The Code
> ---------
> Here is my code:
> // File Name_Id_Table.hpp
>
> template <typename Record_Class,
> const char * TABLE_NAME>
> class Name_Id_Table
> {
> //...
> public:
> void load_from_table(Record_Class& rc)
> {
> rc.id = get_id_from_table();
> rc.name = get_name_from_table();
> }
> };
>
> // File Name_Id.hpp
> #include <string>
> using std::string
Ugh! Yuck!!! Never put a using declaration into a global scope in
a header. NEVER! There is no reason for it to be there. If you
are so inclined to save some typing and use 'string' instead of
'std::string' in your class definition, put the 'using' there, inside
that class definition. Hide your 'using's as deep as possible.
>
> template <int MAX_STRING_WIDTH>
> class Name_Id
> {
> // ...
>
> /* The following line is what I need help with */
> template <> friend class<Name_ID, ????> Name_Id_Table;
What are you trying to accomplish? All possible Name_Id_Table
instantiations with the same Name_ID should be friends or only
the one that has a particular TABLE_NAME?
At this point, it is still possible to have Name_Id_Table template
specialised on the same Name_Id class, but with different table
names. There is nothing in your code that prevents that.
So, do you want a particular fully specialised Name_Id_Table to
be a friend? Then you have to give the address of a constant
character here. Which one? You decide. The easiest solution
would be to give Name_Id an extra argument and pass it along to
the friend class declaration.
>
> private:
> int id;
> string name;
> };
>
>
> // File main.cpp
> #include "Name_Id_Table.hpp"
> #include "Name_Id.hpp"
>
> const char * TITLE_TABLE_NAME = "Titles";
No, that has to be 'extern'.
>
> /* Here is another issue I'm having problems with.
> * I want to declare the types but am having syntax
> * issues.
WHAT syntax issues?
> */
> typedef Name_Id<64> Title;
> typedef Name_Id_Table<Title, TITLE_TABLE_NAME> Title_Table;
>
> int main(void)
> {
> Title t;
> Title_Table table;
>
> table.load_from_table(t);
>
> return EXIT_SUCCESS;
> }
>
>
>
> In the database, I will have three Name-ID tables:
> Title, Author, Publisher. The string widths will
> differ and they will have different table names.
You can create a templated "table of widths" and only worry
about passing the name to your 'Name_Id' template and to the
'Name_Id_Table' template:
---------------------------------------------------------
template<const char* name> struct Name_Id_Aux_Info { enum { MaxWidth }; };
template<typename T, const char* name> class Name_Id_Table;
template<const char* name> class Name_Id {
enum { MAX_STRING_WIDTH =
Name_Id_Aux_Info<name>::MaxWidth };
int foo() { return 42; } // private
friend class Name_Id_Table<Name_Id, name>;
};
template<typename T, const char* name> class Name_Id_Table
{
public:
int bar(T& t) { return t.foo(); }
};
extern const char TITLE[] = "Title";
extern const char AUTHOR[] = "Author";
extern const char PUBLISHER[] = "Publisher";
template<> struct Name_Id_Aux_Info<TITLE> { enum { MaxWidth = 32 }; };
template<> struct Name_Id_Aux_Info<AUTHOR> { enum { MaxWidth = 64 }; };
template<> struct Name_Id_Aux_Info<PUBLISHER> { enum { MaxWidth = 96 }; };
typedef Name_Id<TITLE> id_Title;
typedef Name_Id_Table<id_Title, TITLE> id_Title_Table;
int main()
{
id_Title idt;
id_Title_Table idtt;
idtt.bar(idt);
return 0;
}
> Otherwise they have the same functionality. Each
> table is a singleton; the Title table will not
> contain author or publisher entries. Similarly
> with Author and Publisher tables.
If you tie them by the name only, you have a chance, I believe.
- Next message: Rob Williscroft: "Re: Circular Class Template Friendship"
- Previous message: Jeremie: "Static variables and threads"
- In reply to: Thomas Matthews: "Circular Class Template Friendship"
- Next in thread: Rob Williscroft: "Re: Circular Class Template Friendship"
- Reply: Rob Williscroft: "Re: Circular Class Template Friendship"
- Reply: Thomas Matthews: "Re: Circular Class Template Friendship"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|