Say we have a class that has a private constructor, through friend we can allow some specific class(es) to still create objects of this class:
class Foo
{
friend class Bar;
private:
Foo();
};
class Bar
{
Bar()
{
//create a Foo object
}
};
Now what if I want the opposite of friend, where Foo looks like this:
class Foo
{
//enemy/foe??? class Bar; (if only)
public:
Foo();
};
And then no method of Bar can access the Foo constructor/ make an object of Foo but other classes can (because it's public).
class Bar
{
Bar()
{
Foo foo; //compiler error
}
};
Is such a construct possible or am I stuck with keeping Foo private and adding friends for all the classes?
Such a thing does not exist, and it would be extremely pointless. Imagine you have a situation like this:
class Foo
{
enemy class Bar;
public:
Foo() {}
};
class Bar
{
void evil() { Foo{}; }
};
Nothing prevents the implementor of Bar from doing this:
class Bar
{
void evil() { do_evil(*this); }
};
void do_evil(Bar &self)
{
Foo{};
}
do_evil is not a member of Bar (it's a global function), and so it's not an enemy. Such non-friendliness could therefore be trivially circumvented.
It cannot be done really, but maybe following is enough for you:
template <typename T> struct Tag {};
class Foo
{
public:
template <typename T>
Foo(Tag<T>) {}
Foo(Tag<Bar>) = delete;
// ...
};
And so asking "creator" to "identify" itself.
class Bar
{
Bar()
{
Foo foo{Tag<Bar>{}}; //compiler error
// Foo foo{Tag<void>{}}; // valid as we can cheat about identity.
}
};
There is no such concept in C++.
Public attributes will always be public, but you can limit the exposure of Foo by making the constructor protected, for instance, and only visible for selected classes (although limiting friend is advised). Perhaps also make Foo as a protected class of Bar2 because only Bar2 or its children will actually use it.
As it has already been sayed by others, your desire breaks the idea of encapsulation because you cannot always know who your enemies are.
But, still, there is a possibility to get (almost) what you want:
#include <type_traits>
struct enemy; // We need a forward declaration of your enemy
struct my_class {
// The access is done using a factory, where the caller has to tell
// us his own name
template <class T>
struct make{
static_assert(!std::is_same<T,enemy>::value,"you are my enemy.");
friend T;
private:
my_class operator() () { return my_class{}; }
};
private:
my_class(); // This is the constructor we care about
};
struct no_enemy {
void bar() {
my_class a = my_class::make<no_enemy>{}(); // works
}
};
struct enemy {
void bar() {
my_class b = my_class::make<enemy>{}(); // error: static_assert failed
my_class c = my_class::make<no_enemy>{}(); // error: foo is "private"
}
};
Related
I am trying to use EXPECT_CALL to set the return value of the function that resides in a different class than what the mock class inherits from.
In the following snippet, I was wondering if there's a way to use EXPECT_CALL on someFunction() that's a public function of Bar inside a unit test through bar object of UnitTest class but it seems to error out.
One thing I know is I would need to use MOCK_METHOD for someFunction to override it to expect EXPECT_CALL but not sure how could I do inside the Mock class?
// Bar.hpp
class Bar
{
public:
virtual bool someFunction();
};
// Foo.hpp
namespace sw::foo_state
{
class Foo
{
Bar _bar;
public:
Foo(Bar&& bar) : _bar(std::move(bar)) {}
void TestFunction()
{
_bar.someFunction();
}
};
};
// MockClass.hpp
namespace sw
{
class Mock : public foo_state::Foo
{
Mock(Bar&& bar) : Foo(std::move(bar)) {}
};
};
// UnitTest.cpp
using namespace sw::foo_state;
class UnitTest
{
public:
Bar bar;
auto ptr = std::make_unique<Mock>(std::move(bar));
};
TEST_F(UnitTest, Test)
{
EXPECT_CALL(bar, someFunction()).WillOnce(Return(true)); // error: ‘class sw::foo_state::Bar’ has no member named ‘gmock_someFunction’; did you mean ‘someFunction’?
ptr->TestFunction();
}
EDIT:
You only need to change your class Foo constructor to accept a pointer or a reference to take advantage of class Bar polymorphism:
class Bar
{
public:
virtual bool someFunction()
{
return true;
}
};
class Foo
{
public:
Foo(Bar& bar): _bar{ bar} {}
void TestFunction()
{
std::cout << _bar.someFunction() << std::endl;
}
private:
Bar& _bar; // can also be std::unique_ptr<Bar> if you prefer to own the object
};
struct MockBar : public Bar
{
MOCK_METHOD0(someFunction, bool());
};
using testing::Return;
TEST(xxx, yyy)
{
MockBar mBar;
// ON_CALL(mBar, someFunction()).WillByDefault(Return(false)); // if you don't want to force expectation
EXPECT_CALL(mBar, someFunction()).WillOnce(Return(false));
Foo foo(mBar);
foo.TestFunction();
}
I want to have a template that can access the protected method of it's typename parameter. How can I make that work?
For example:
class Foo{
...
protected:
int Bar();
}
template <class T> FooTempl{
...
int SomeMethod(T* ptr) { return ptr->Bar();};
...
}
The reason is that I want the method Foo::Bar() to be accessible to the template, but not to any other external caller. I hope there's some friend syntax there that can make it work...
An alternate to declaring FooTempl as a friend of Foo would be to have the former derive from the latter. In this case, since Foo is a base class for FooTempl, so FooTempl::SomeMethod would not need to have a Foo * parameter anymore.
class Foo
{
protected:
int Bar() { return 42; }
};
template <class T>
class FooTempl : public T
{
public:
int SomeMethod() { return T::Bar();}
};
int main()
{
FooTempl<Foo> bar;
bar.SomeMethod();
}
Which of these methods is more appropriate depends on your use case.
Add the following line into Foo:
template<typename T> friend class FooTempl;
I suspect I can't do this directly using a PIMPL pattern. Is it possible to have a smart pointer to a template class? I have not been able to compile by turning knobs on the shared_ptr declaration.
// ============Foo.h ============
// Forward declare the implementation
template <typename T> class FooImpl;
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImpl<T> > m_impl;
};
// ============FooImpl.h ============
template <typename T>
class FooImpl
{
...
};
Under Visual Studio 2008: "error C2065: 'T' : undeclared identifier". I receive a similar error under GCC. If I un-parameterize FooImpl (so that FooTempl inherits from FooImpl), the code will compile.
I suspect I can't paramaterize the smart pointer, but I could be wrong.
EDIT: The second Visual Studio error is more telling: "error C3203: 'FooImpl' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type"
Jeff
I'm not entirely certain what you are trying to accomplish, but does this help?
Try 1:
// ============Foo.h ============
// Forward declare the implementation
template <typename T> class FooImpl;
template<class C>
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImpl<C> > m_impl;
};
// ============FooImpl.h ============
template <typename T>
class FooImpl
{
...
};
Try 2:
// ============Foo.h ============
// Forward declare the implementation
class FooImplBase;
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImplBase > m_impl;
};
// ============FooImpl.h ============
class FooImplBase {
public:
virtual void AnAPI();
virtual int AnotherAPI();
};
template <typename T>
class FooImpl : public FooImplBase
{
...
};
The code you have posted cannot compile since T does not mean anything in the context of Foo. The compiler expects a type called T here which does not exist there... Not entirely sure what you are trying to accomplish, but wouldn't the following solve your problem?
// ============Foo.h ============
class FooImplBase {
virtual void WhateverFooImplIsSupposedToDo() = 0;
};
template <typename T> class FooImpl : public FooImplBase {
T mInstance;
public:
FooImpl(T const & pInstance) : mInstance(pInstance) {}
virtual void WhateverFooImplIsSupposedToDo()
{
// implementation which deals with instances of T
}
};
class Foo
{
public:
Foo getInstance(const string& fooType) {
// use m_impl->WhateverFooImplIsSupposedToDo...
}
template < class T >
Foo( T const & pInstance ) : m_impl(new FooImpl<T>(pInstance)) {}
private:
shared_ptr< FooImplBase > m_impl;
};
You're doing it right, just make sure T is defined. This compiles for me on MSVC++ 2010:
#include <memory>
using namespace std;
template<class T>
class Blah {
public:
Blah() { }
};
class Foo {
public:
shared_ptr<Blah<int>> ptr;
Foo() : ptr(new Blah<int>()) { }
};
If you're on an older compiler that hasn't incorporated this feature of C++11 yet, change
shared_ptr<Blah<int>> ptr;
To
shared_ptr<Blah<int> > ptr;
So the compiler doesn't think the >> is a right shift. C++11 doesn't have this problem though.
I don't know in advance I am going to have a Blah, only a Blah.
From the language point of view, Blah<T> is meaningless because T doesn't exist. Depending on what you're exactly trying to do, you can
make Foo a template, too, so that you can declare a template parameter T:
template<typename T>
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImpl<T> > m_impl;
};
which 'fixes' the choice of T when you declare a variable of type Foo<T>;
or make FooImpl explicitly derive from a common base:
class FooBase {
// need to define the interface here
};
// this is a class definition whereas previously you only needed a declaration
template<typename T>
class FooImpl: public FooBase {
// definition here
};
class Foo
{
public:
Foo getInstance(const string& fooType);
// we needed the definition of FooImpl for this member
// in addition this member is quite obviously a template
template<typename T>
void
set(FooImpl<T> const& foo)
{
m_impl.reset(new FooImpl<T>(foo));
}
// not a member template!
void
use()
{
// any use of m_impl will be through the FooBase interface
}
private:
shared_ptr<FooBase> m_impl;
};
where for a given Foo instance any kind of FooImpl<T> can be set dynamically and then used through the FooBase interface. This is a kind of type erasure as it's called in the C++ world.
We can use templates to write a generic smart pointer class. Following C++ code demonstrates the same. We don't need to call delete 'ptr', when the object 'ptr' goes out of scope, destructor for it is automatically.
#include<iostream>
using namespace std;
// A generic smart pointer class
template <class T>
class SmartPtr
{
T *ptr; // Actual pointer
public:
// Constructor
explicit SmartPtr(T *p = NULL) { ptr = p; }
// Destructor
~SmartPtr() {
cout <<"Destructor called" << endl;
delete(ptr);
}
// Overloading dereferncing operator
T & operator * () { return *ptr; }
// Overloding arrow operator so that members of T can be accessed
// like a pointer (useful if T represents a class or struct or
// union type)
T * operator -> () { return ptr; }
};
int main()
{
SmartPtr<int> ptr(new int()); // Here we can create any data type pointer just like 'int'
*ptr = 20;
cout << *ptr;
return 0;
}
out put:
20
Destructor called
I have a template class for which I need to access a protected member function of the template parameter, like this:
class Foo
{
protected:
void foo() {}
};
template<typename T>
class Bar
{
public:
static void bar(T& self){self.foo();}
};
...
Foo f;
Bar<Foo>::bar(f);
My problem is getting access to the protected method. I tried putting a friend class T into Bar, but that doesn't seem to be allowed in c++ (edit: and wouldn't solve my problem anyways, so it seemd). I tried letting Bar inherit from T (template<typename T> class Bar: public T (could have used private inheritance, but the public interface of Bar is not terribly important, since the class itself is internal only)), but that didn't allow for access of foo() either. So how do I get access to the foo() method?
Edit:
Foo should not need to know Bar<Foo>, since there are quite a lot Bar classes. I can however make other changes to Foo (without changing the public interface of course).
OK, this is a "rot in hell" hack. You can abuse the fact that you can form pointers-to-members pointing to protected base members from a derived class.
class Foo
{
protected:
void foo() {}
};
// Helper template to bypass protected access control
// for a member function called foo, taking no parameters
// and returning void.
template<typename T>
struct Unprotect : public T
{
typedef void (T::*FooPtr)();
static FooPtr GetFooPtr()
{
return &Unprotect::foo;
}
};
template<typename T>
class Bar
{
public:
static void bar(T& self){(self.*Unprotect<Foo>::GetFooPtr())();}
};
int main()
{
Foo f;
Bar<Foo>::bar(f);
}
You did your friend declaration in the wrong direction. If Bar says Foo is it's friend, that means Foo gets access to Bar's private data. For Bar to get access to Foo's private data, Foo has to say Bar is its friend.
template<typename T>
class Bar
{
public:
static void bar(T& self){self.foo();}
};
class Foo
{
protected:
void foo() {}
friend class Bar<Foo>;
};
void main()
{
Foo f;
Bar<Foo>::bar(f);
}
If you want to access a protected member a derived class of this, you can do it with the using keyword:
class A
{
protected:
void i_am_protected () {}
};
template <class T>
class B : public T
{
using T::i_am_protected;
void call_me ()
{
i_am_protected(); // OK.
this->i_am_protected(); // This compiles without the keyword.
}
};
If you need B to access a protected member of A when an object is passed to B, you need to declare B as a friend of A:
class A
{
template <class T>
friend
class B;
protected:
void i_am_protected () {}
};
template <class T>
class B : public T
{
void call_me (T& obj)
{
obj.i_am_protected(); // OK.
}
};
I have two classes that depend on each other:
class Foo; //forward declaration
template <typename T>
class Bar {
public:
Foo* foo_ptr;
void DoSomething() {
foo_ptr->DoSomething();
}
};
class Foo {
public:
Bar<Foo>* bar_ptr;
void DoSomething() {
bar_ptr->DoSomething();
}
};
When I compile it in g++, it was giving error of "Invalid use of incomplete type", but it was compiled nicely in MSVC 10.
Is it possible to solve this problem while keeping the declaration and definition in one header file? (no cpp files)
If this is not allowed in the standard, so is this one of the MSVC "bug" or "feature"?
Yes, just move the method definitions out of the class definition:
class Foo; //forward declaration
template <typename T>
class Bar {
public:
Foo* foo_ptr;
void DoSomething();
};
class Foo {
public:
Bar<Foo>* bar_ptr;
void DoSomething() {
bar_ptr->DoSomething();
}
};
// Don't forget to make the function inline or you'll end up
// with multiple definitions
template <typename T>
inline void Bar<T>::DoSomething() {
foo_ptr->DoSomething();
}
See this page:
What is the best way to deal with co-dependent classes in C++?
It should clear up the problem and provides a couple nice solutions.
It works when you replace Foo* foo_ptr; by the template parameter T so that you get T* foo_ptr;. In this foo_ptr does not necessarily have to be a pointer or be predefined.
template <typename T>
class Bar {
public:
T foo;
void DoSomething() {
foo.DoSomething();
}
};
class Foo {
public:
Bar<Foo>* bar_ptr;
void DoSomething() {
bar_ptr->DoSomething();
}
};