I would like to define a staitc member funtion to build my class. This staitc function would access private member, and I make it as friend.
Here is the demo code:
#include <memory>
template<typename T>
class Foo
{
public:
static std::unique_ptr<Foo> Create();
friend static std::unique_ptr<Foo> Foo::Create();
};
template<typename T>
std::unique_ptr<Foo<T>> Foo<T>::Create()
{
return std::unique_ptr<Foo<T>>();
}
template class Foo<int>;
template class Foo<double>;
int main()
{
return 0;
}
It compiles faild. How to fix it?
As stated in the comments, you don't need it. Why? Because static member functions are still member functions, meaning they can access private members of the class. I'm assuming that this was the confusion. A small (somewhat contrived) example:
#include <iostream>
#include <memory>
// templated class with private member "data"
template <typename T>
class Foo {
public:
// static Create function
static std::unique_ptr<Foo> Create(T value) {
auto foo_ptr = std::make_unique<Foo>();
// can change private members
foo_ptr->data = value;
return foo_ptr;
}
// function to access private member in main
void printData() {
std::cout << data << std::endl;
}
private:
T data;
};
int main() {
auto foo_int = Foo<int>::Create(2);
foo_int->printData(); // will print 2!
return 0;
}
Related
Is it possible to have callback to member of template class, as depicted above? I mean, I have some template class, there is defined object of another (non-template) class. That object has another member function. I would like to invoke from that member function the member function of template class. Is it feasible?
This is how I understand the problem. A class called 'some_class' (MyAlgorithm) supposed to have a reference to template (AlgorithmConsumer). Since 'some_class' requires only one method, the easiest way is to pass a reference to the function, something like this:
#include <iostream>
#include <functional>
class MyAlgorithm
{
std::function<void()> prepare;
public:
explicit MyAlgorithm(std::function<void()> prepare)
: prepare{prepare}
{}
void do_something()
{
if (prepare)
{
prepare();
}
std::cout << "I did something\n";
}
};
template<typename T>
class AlgorithmConsumer
{
MyAlgorithm algorithm;
public:
AlgorithmConsumer()
: algorithm([this](){prepare();})
{}
void prepare()
{
std::cout << "Preparing...\n";
}
void execute()
{
algorithm.do_something();
}
};
int main()
{
AlgorithmConsumer<int> ac;
ac.execute();
return 0;
}
Hope, this solves your problem.
Here's one way to do it without using std::function
struct B{
template<class T>
void CallTemplateFun(void (T::*funPtr)(), T& instance){
(instance.*funPtr)();
}
};
template<typename T>
class A{
T t;
B b;
public:
A(T v) : t(v){}
void print(){ std::cout << t << std::endl ; }
};
int main(
{
A<int> ai(5);
B b;
b.CallTemplateFun(&A<int>::print, ai);
A<float> af(3.1428f);
b.CallTemplateFun(&A<float>::print, af);
return 0;
}
Is it possible to use SFINAE and std::enable_if to disable a single member function of a template class?
I currently have a code similar to this:
#include <type_traits>
#include <iostream>
#include <cassert>
#include <string>
class Base {
public:
virtual int f() { return 0; }
};
template<typename T>
class Derived : public Base {
private:
T getValue_() { return T(); }
public:
int f() override {
assert((std::is_same<T, int>::value));
T val = getValue_();
//return val; --> not possible if T not convertible to int
return *reinterpret_cast<int*>(&val);
}
};
template<typename T>
class MoreDerived : public Derived<T> {
public:
int f() override { return 2; }
};
int main() {
Derived<int> i;
MoreDerived<std::string> f;
std::cout << f.f() << " " << i.f() << std::endl;
}
Ideally, Derived<T>::f() should be disabled if T != int. Because f is virtual, Derived<T>::f() gets generated for any instantiation of Derived, even if it is never called.
But the code is used such that Derived<T> (with T != int) never gets created only as a base class of MoreDerived<T>.
So the hack in Derived<T>::f() is necessary to make the program compile; the reinterpret_cast line never gets executed.
You could simply specialize f for int:
template<typename T>
class Derived : public Base {
private:
T getValue_() { return T(); }
public:
int f() override {
return Base::f();
}
};
template <>
int Derived<int>::f () {
return getValue_();
}
No you can't rule out a member function with SFINAE. You could do it with specialisation of your Derived class f member function for convertible Ts to int but that would lead to unnecessary duplication of code. In C++17 however you could solve this with use of if constexpr:
template<typename T> class Derived : public Base {
T getValue_() { return T(); }
public:
int f() override {
if constexpr(std::is_convertible<T, int>::value) return getValue_();
return Base::f();
}
};
Live Demo
I have a class MyClass declaration in a header file interface.h and some static functions (foo and bar and a few more) in file1.cpp. The static functions are only used inside file1.cpp but they need to modify private/protected members of MyClass`.
// in "interface.h"
class MyClass {
// maybe declare as friend?
// friend static void foo(MyClass &ref);
private:
double someval;
}
// in "file1.cpp"
static void foo(MyClass &ref) {
ref.someval = 41.0;
}
static void bar(MyClass &ref) {
ref.someval = 0.42;
}
// function that uses foo/bar
void doSomething(MyClass &ref) {
foo(ref);
}
Idea 1: Somehow declare them as friends of MyClass?
Why its not good: They are static AND are in a different compilation unit. Besides that would expose them to the user of MyClass who does not need to know anything about them.
Idea 2: Don't have idea 2.
Sort of linked: Is it possible to declare a friend function as static?
Sort of linked: Is it possible to declare a friend function as static?
Personally I find the whole friend thing a bit of a hack that breaks encapsulation but you've asked a valid question and the answer is that you can achieve what you want with a helper class:
file1.h
class MyClass {
private:
double someval;
friend class MyClassHelper;
};
file1.cpp
#include "file1.h"
struct MyClassHelper {
static void mutateMyClass(MyClass& ref) {
ref.someval=42;
}
};
// in "file1.cpp"
static void foo(MyClass &ref) {
MyClassHelper::mutateMyClass(ref);
}
Are you really sure you want to do it like this? Are you sure you don't want to encapsulate MyClass's mutators inside MyClass itself?
As weird as it may sound (and look), you can actually read & write private members of a class / struct.
It's not pretty, and certainly not encouraged, but doable.
template<typename T>
struct invisible
{
static typename T::type value;
};
template<typename T>
typename T::type invisible<T>::value;
template<typename T, typename T::type P>
class construct_invisible
{
construct_invisible(){ invisible<T>::value = P; }
static const construct_invisible instance;
};
template<typename T, typename T::type P>
const construct_invisible<T, P> construct_invisible<T, P>::instance;
struct MyClass_someval{ typedef double MyClass::*type; };
template class construct_invisible<MyClass_someval, &MyClass::someval>;
static void foo(MyClass &ref) {
ref.*invisible<MyClass_someval>::value = 41.0;
}
When I first saw it I also thought: HOLY S***!
// in "interface.h"
class MyClass {
// maybe declare as friend?
// friend static void foo(MyClass &ref);
public:
friend class SetSomevalClass; // make the classes friends
private:
double someval;
};
class SetSomevalClass // functor class(or function class)
{
public:
double operator()(MyClass n, double data) // this could have been void
{
n.someval = data; //set somevalue to data
return n.someval; //return somevalue
// return is solely used to show result in foo() and bar()
}
};
// in "file1.cpp"
static void foo(MyClass &ref)
{
SetSomevalClass s; //create functor object
//s(ref, 40);
//this would be the end of the foo function(uncommented) if we did not want to show the result
std::cout << "foo()" << s(ref, 40) << std::endl;
//simply to show result
}
static void bar(MyClass &ref)
{
SetSomevalClass s;
//s(ref,2);
//this would be the end of the foo function(uncommented) if we did not want to show the result
std::cout << "bar()" << s(ref, 2) << std::endl;
}
// function that uses foo/bar
void doSomething(MyClass &ref) //calls both foo() and bar()
{
foo(ref);
bar(ref);
}
int main()
{
MyClass s;
doSomething(s);
}// end main
Basically, I need to set a variable outside of the constructor and make it accessible to the entire class.
It would need to work something like this:
#include <iostream>
#include <string>
template <typename MT>
class CallbackFunction
{
void (*func)(MT);
MT *data;
public:
void SetCallbackData (void (*f)(MT), MT *d)
{
func = f;
data = d;
}
void Call()
{
func(data);
}
};
class Callback
{
public:
template <typename T>
void SetCallback(CallbackFunction <T> *func)
{
// Need to make this a class member;
CallbackFunction <T> *CallbackClass = func;
}
void Call()
{
CallbackClass->Call();
}
};
template <typename CT>
Callback *NewCallback(void (*func)(CT), CT *data)
{
Callback *cb;
CallbackFunction <CT> *cf;
cf->SetCallbackData(func, data);
cb->SetCallback <CT> (cf);
return cb;
};
void Call(Callback *CallbackFunc)
{
CallbackFunc->Call();
}
void foo(std::string str)
{
std::cout << str << "\n";
}
int main()
{
std::string *str;
str->append("Hello, World!");
Call( NewCallback(foo, str) );
return 0;
}
More details:
I know it's buggy, and it doesn't compile, I'll sort out those bugs when I find a solution to my problem. Which is:
I need to find a way to declare a template variable inside a member function of the class "Callback". I need to do this because the class "Callback" cannot be a template, it needs to remain a simple class. So because the class "Callback" is not a template, I need to make one of it's member functions a template instead. So that member function can declare a variable of the type defined (with the template) when the function is called, and this variable needs to be accessible to the entire class.
So in a nice list:
class "Callback" cannot be a template,
variable CallbackClass must be accessible to the entire class,
but remain inside of the class.
#include <iostream>
#include <string>
#include <memory>
template <typename MT>
class CallbackFunction
{
typedef void (*func_ptr)(MT);
func_ptr f_ptr;
typedef std::shared_ptr<MT> data_ptr;
data_ptr data_p;
public:
void SetCallbackData (func_ptr f_ptr_, MT *d)
{
f_ptr = f_ptr_;
data_p.reset(d);
}
void Call()
{
if ( f_ptr ) f_ptr(data);
}
};
template<class T>
class Callback
{
public:
template <typename T>
void SetCallback(CallbackFunction <T> *func)
{
f_ptr.reset(func);
}
void Call()
{
if ( f_ptr ) f_ptr->Call();
}
typedef std::shared_ptr<CallbackFunction<T>> func_ptr;
static func_ptr f_ptr;
};
I would implement this using polymorphism. Your programming skills seem good so I will just sketch the direction to solution, feel free to ask for more help if needed.
// your callbackobjects inherit from this class, the sole purpose of this
// class is to provide the Call interface. The derived classes implement
// their custom version of Call().
class CallBackObject{
public:
virtual void Call(){};
};
class Callback
{
CallBackObject *callBackObject;
public:
void SetCallback(CallBackObject *o)
{
callBackObject = o;
}
void Call()
{
callBackObject -> Call();
}
};
Create an abstract interface Callback class and have your CallbackFunction<T> inherit from this. Have your Callback class hold a pointer to this abstract interface. Finally, have your Callback::SetCallback assign func to this pointer.
Here's some code to illustrate the idea:
class ICallback
{
public:
virtual ~ICallback() {}
virtual void Call() = 0;
};
template <typename MT>
class CallbackFunction : public ICallback
{
typedef void (*callback)(MT);
callback myfunc;
MT *data;
public:
CallbackFunction (callback f, MT *d) :
myfunc (f),
data (d)
{}
void Call()
{
if(myfunc && data)
{
myfunc(*data);
}
else throw std::logic_error("Callback function or data is null!");
}
};
Then have Callback hold a ICallback*:
class Callback
{
ICallback *mycallback;
public:
template <typename T>
void SetCallback(CallbackFunction <T> *func)
{
// Need to make this a class member;
// CallbackFunction <T> *CallbackClass = func;
mycallback = func;
}
void Call()
{
mycallback->Call();
}
};
The idea is to make all instantiated templates of CallbackFunction <T> a kind-of ICallback. Now the class using ICallback can take any class CallbackFunction <T> without needing to know what T is.
I want do make some classes, which will have private/protected constructors, and will have static method named create().
Let me show you the code:
template <class T>
struct ServicePtr
{
std::shared_ptr<T> service;
};
template <class T>
struct ServicePtrDeleter
{
void operator()(T* ref) const
{
if (ref->service.get())
{
}
delete ref;
}
};
template <typename T>
struct ServiceCreator
{
static std::shared_ptr< ServicePtr<T> > create()
{
std::shared_ptr< ServicePtr<T> > servicePtr(new ServicePtr<T>);
servicePtr->service.reset(new T);
return servicePtr;
}
};
class S:public IService,
public ServiceCreator<S>
{
protected:
S()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
public:
virtual ~S()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main()
{
auto s=S::create();
return 0;
}
Compiling with GCC 4.6.1, I am given the following error:
main.cc: In static member function 'static std::shared_ptr > ServiceCreator::create() [with T = S]':
main.cc:310:12: instantiated from here
main.cc:275:3: error: 'S::S()' is protected
main.cc:177:3: error: within this context
make: * [main.o] Error 1
In ServiceCreator::create(), you do this:
servicePtr->service.reset(new T);
If T is S, this tries to create an S, but fails because S has a protected constructor. To allow an unrelated class to access that constructor, while keeping it protected, you will have to make the creator class (or just the member function that needs access) a friend:
friend ServiceCreator<S>::create;
The main problem is that ServiceCreator<T>::create() is going to try and instantiate S over here:
static std::shared_ptr< ServicePtr<T> > create()
{
// ...
servicePtr->service.reset(new T); // T = class S
return servicePtr;
}
But of course it cannot do that because class S's constructor is protected! An easy way to fix this is to just make ServiceCreator a friend to S:
class S : public IService, public ServiceCreator<S>
{
friend class ServiceCreator<S>;
// ...
};