I am writing a small class, the class is basically a factory for the C class, but I want other classes to be able to access some of the methods.
template<class C>
class CFactory {
public:
friend class C;
};
This should make the fields of CFactory available to the class C, but the compiler thinks otherwise.
I'm getting the following two errors using gcc on a mac.
error: using template type parameter 'C' after 'class'
error: friend declaration does not name a class or function
Can anyone tell me what I'm doing wrong and how to get et right?
Unfortunately, in my understanding, this isn't allowed in current standard.
§7.1.5.3/2 says:
[Note: ... within a class template
with a template type-parameter T, the
declaration
friend class T;
is ill-formed. -end note]
On a related note, this restriction seems to be removed in C++0x
(§11.3/3 in N3290).
Incidentally, MSVC may allow this if we write simply friend T;.
Ise's response is correct -- Comeau's FAQ contains a question concerning this issue in more detail.
However, perhaps you can try an extra template indirection that might work? Something like this:
template <typename T>
struct FriendMaker
{
typedef T Type;
};
template <typename T>
class CFactory
{
public:
friend class FriendMaker<T>::Type;
};
This seems to only work with gcc 4.5.x however so I wouldn't rely on it.
C can be anything - int, double, etc. and they are not classes. In general, this class C is not class. And you cannot have something like:
class A
{
friend class int;
//..
};
One more reason to prefer typename, instead of class when using templates
Related
Compiling the following code
template<typename T>
class t1 {
};
class t1 {
};
Gives the following error
error: template argument required for ‘class t1’
It's literally been years since I've used C++ enough to delve into templates (I've decided to pick it back up and learn C++ 11/14), so I'm probably mistaken, but I thought this was legal.
Can someone advise? If you wanted to do something like this, how would you go about doing it?
No, you can't do this.
Unlike a function template, a class template cannot be overloaded. t1 has been declared as a class template, the only thing you can do is specialize it:
template <>
class t1<int> {
};
You could do something like this with variadic templates:
template<typename...>
struct myclass;
template<>
struct myclass<>{};
template<typename T>
struct myclass<T>{};
But I can think of little use other than template metaprogramming and you still have to use template syntax: myclass<>
When programming with C++ templates, I often find it useful to define a type alias member called type. I've defined a kind of "identity" template:
template <typename T>
struct id { using type = T; };
I quite like that I can then often avoid putting anything between the braces of a class definition; inheriting from an id specialisation instead. A trivial primary template example might then be:
template <typename,typename>
struct Foo : id<void> {};
Does something like id exist in the standard library; or Boost?
yes, sort of.
std::enable_if<true, T>
I caught myself "inventing" this simple construct lately when working with many templated classes and deriving from them. I am not sure if it is common practice, or am I tying a rope around my neck.
template <typename T> class Base {};
template <typename T> class Derived : public Base<T>{
typedef Base<T> Base;
};
I found it especially useful if the Base class has its own typedefs for some types. E.g:
template <typename T> class Base {
typedef T Scalar;
typedef Matrix<Scalar> Matrix;
};
Then it's easy to "import" types into the Derived. It saves re-typing the template signature. E.g:
template <typename T> class Derived : public Base<T>{
typename Base<T>::Matrix yuck_yuck(); //that's what I am trying to simplify
typedef typename Base<T> Base;
typedef typename Base::Matrix Matrix;
Matrix much_fun(); //looks way better
};
Also on of the big advantages is that, when you want to add another template parameter to the Base class. You don't have to go over a bunch of functions to change, just update the typedef. much_fun will have no problem if Base will be changed to Base<T,U> while yuck_yuck will need to have updated signatures (not sure if template parameter is formally included with the signature, so pardon me if I am making a formal error here, but I think it is).
Is this a good practice or am I playing with a gun next to my vital parts? It looks like it makes code more readable, and simplifies it, but maybe I am missing something that can backfire.
EDIT2: I got the working example. The Base class must be within its namespace or there will be conflicts with the same names within a scope, as the commenters pointed out. Below is the minimal example that embodies my real question.
namespace Fun {
template <typename T> class Base {
public:
typedef T Scalar;
};
}
template <typename T>
class Derived : public Fun::Base<T>{
public:
typedef typename Fun::Base<T> Base;
typedef typename Base::Scalar Scalar;
typename Fun::Base<T>::Scalar yuck_yuck();
Scalar much_fun();
};
#include <iostream>
using namespace std;
int main() {
Derived<double> d;
return 0;
}
With lots of stuff the code gets really bloated with typenames, and template parameters. But I already run into a trouble making up the example, by not placing Base in its own namespace. I wonder if there are any other caveats, that are actually killers to the idea.
I believe this is ill-formed, due to rule 2 of C++11 3.3.7/1
A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S.
meaning that you can't use the name Base to refer to both the template and the typedef within the class scope. Certainly, my compiler won't accept it:
error: declaration of ‘typedef struct Base<T> Derived<T>::Base’ [-fpermissive]
error: changes meaning of ‘Base’ from ‘struct Base<T>’ [-fpermissive]
(NOTE: this refers to the simplified example originally posted, and doesn't cover the updated question where the base class name is in a different scope.)
I actually consider it a helpful (and good) practice if the typedef is not exposed public or protected:
// No template, not Base, to avoid that discussion
class Derive : public SomeBaseClass
{
private:
typedef SomeBaseClass Base;
public:
typedef Base::T T;
T f();
};
class MoreDerived : public Derived
{
// Base is not accessible
};
I'd like to place a POD type constrain on type parameter T of class template A and then derive another class template B from the satisfactory A. Besides, B is supposed to have different implementation according to constancy of instance of A. The purpose of doing all this is about, well you know, for better type checking before runtime.
All I can figure out is a tentative definition of A
template <typename T, typename POD=void>
class A;
template <typename T>
class A <T, std::enable_if<std::is_pod<T>::value>::type>
{
//blah...
};
so that A can't be instantialized when passing non-POD type, as you might have noticed that partial parameterization does the trick like a type switch.
But I can't figure out how B could be defined. I presume it looks like the following
template <typename A?>
class B;
template <>
B<const A?> : public A?
{
//blah...
};
template <>
B<A?> : public A?
{
//blah...
};
Any brilliant idea?
PS: Personally I tend to be highly critical. But just post how you think this could be done anyway.
There is no brilliant idea if the specializations are going to be completely different. You have to go with this:
template <typename T>
class B;
template <typename T>
class B<const A<T>> : public A<T>
{
};
template <typename T>
class B<A<T>> : public A<T>
{
};
which is almost same as you've written yourself except ? symbol.
You can instantiate this class as:
B<A<int>> x; //it chooses the second specialization
B<const A<int>> y; //it chooses the first specialization
See online demo. Note that you've forgotten typename here:
typename std::enable_if<std::is_pod<T>::value>::type
I fixed that too.
If some code in the specializations are going to be same, then you could do some trick in order to share the common part, but I cannot suggest anything as I don't know what you're going to put in the specializations.
Example:
template<class T>
class Base {
public:
Base();
friend class T;
};
Now this doesn't work... Is there a way of doing this?
I'm actually trying to make a general class sealer like this:
class ClassSealer {
private:
friend class Sealed;
ClassSealer() {}
};
class Sealed : private virtual ClassSealer
{
// ...
};
class FailsToDerive : public Sealed
{
// Cannot be instantiated
};
I found this example on this site somewhere but I can't find it... (here)
I know there are other ways of doing this but just now I'm curious if you actually can do something like this.
It is explicitly disallowed in the standard, even if some versions of VisualStudio do allow it.
C++ Standard 7.1.5.3 Elaborated type specifiers, paragraph 2
3.4.4 describes how name lookup proceeds for the identifier in an
elaborated-type-specifier. If the
identifier resolves to
a class-name or enum-name,
the elaborated-type-specifier introduces
it into the declaration the same
way a simple-type-specifier introduces
its type-name. If the identifier resolves
to a typedef-name or a
template type-parameter,
the elaborated-type-specifier is
ill-formed. [Note: this implies that,
within a class template with a
template type-parameter T, the
declaration friend class T; is
ill-formed. ]
I recognize the code above as a pattern to seal (disallow the extension of) a class. There is another solution, that does not really block the extension but that will flag unadvertidly extending from the class. As seen in ADOBE Source Library:
namespace adobe { namespace implementation {
template <class T>
class final
{
protected:
final() {}
};
}}
#define ADOBE_FINAL( X ) private virtual adobe::implementation::final<T>
with the usage:
class Sealed : ADOBE_FINAL( Sealed )
{//...
};
While it allows extension if you really force it:
class SealBreaker : public Sealed, ADOBE_FINAL( Sealed )
{
public:
SealBreaker() : adobe::implementation::final<Sealed>(), Sealed() {}
};
It will restrict users from mistakenly do it.
EDIT:
The upcoming C++11 standard does allow you to befriend a type argument with a slightly different syntax:
template <typename T>
class A {
// friend class T; // still incorrect: elaborate type specifier
friend T; // correct: simple specifier, note lack of "class"
};
I found a simple trick to declare template parameters as friends:
template < typename T>
struct type_wrapper
{
typedef T type;
};
template < typename T> class foo
{
friend class type_wrapper < T>::type
}; // type_wrapper< T>::type == T
However I do not know how this could help to define an alternative version of a class sealer.
Do you really need to do this?
If you want to prevent someone from deriving from your class, just add a comment and make the destructor non-virtual.