Declare static functions as friend function? - c++

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

Related

Select which member function to call at compile time

I have a templated class on some object T. T defines two member functions bar and foo
template<class T>
class A {
public:
void f() {
t_.bar();
t_.foo();
}
private:
T t_;
};
Now I would like be able to tell A (ideally at compile time), to call either foo or bar, but not both. So the idea is to tell A at construction time which member function of T to call.
The solution I have currently in place is to pass a callable void callMember(const T& t) { return t.foo(); } in A's constructor to at runtime call the right member, but I'm wondering if there is a better solution?
You can add a bool template parameter to A that tells it which member function of T to call, and then use a constexpr if on that parameter in the body of f:
template<class T, bool Choice>
class A {
public:
void f() {
if constexpr(Choice) // doesn't strictly have to be constexpr
// if T defines both bar and foo
t_.bar();
else
t_.foo();
}
private:
T t_;
};
Now for some type like:
struct S {
void bar() { std::cout << "bar"; }
void foo() { std::cout << "foo"; }
};
you can do:
A<S, true> a;
a.f(); // calls S::bar
A<S, false> b;
b.f(); // calls S::foo
Here's a demo.
I assume its Ok to have instantiations of A be of different type depending on which method is called. If that is the case I suggest to choose between two types rather than two methods.
Say X is the type with the two methods, then you can do this:
struct X {
void foo() {}
void bar() {}
};
struct Xfoo {
X x;
void foobar() { x.foo(); }
};
struct Xbar {
X x;
void foobar() { x.bar(); }
};
Now the template is:
template<class T>
class A {
public:
void f() {
t_.foobar();
}
private:
T t_;
};
And you either instantiate A<Xfoo> or A<Xbar> rather than A<X>.
I suppose you have more than just one type X, then Xfoo and Xbar can be parametrized on the type to be wrapped.

How to make a static template member function as friend

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;
}

check return type from templated method

I am working on c++11 application:
There I have some templated methods:
template <class P, class T>
void copyMemberToDocument(const P &childClass
std::string (T::*getter) (void) const) {
auto member = (childClass.*getter)();
// ...
}
Child class has multiple inheritance so I can have something like:
class A {
public:
int getA() {return 1;}
class B {
public:
const char* getB() {return "hello";}
class C : public A, public B {};
So I can do something like:
C c;
copyMemberToDocument(c, &B::getB);
copyMemberToDocument(c, &A::getA);
Is is possible to know if return value in templated method will be "const char*" or "int" in order to do different things depending on that?
Correct implementation is:
template <class P, class T>
void copyMemberToDocument(const P childClass, T getter) {
static_assert(std::is_member_function_pointer<T>::value,
"getter is not a member function.");
using member_type = decltype((std::declval<P>().*getter)());
member_type member = (childClass.*getter)();
}
Now, if you need different code executed, depending on the type member_type, you can use overloading of function, class specialisation or c++17's if constexpr.
if constexpr(std::is_same_v<int,member_type>) {
std::cout<<"I am a int member\n";
}
if constexpr(std::is_same_v<std::string,member_type>) {
std::cout<<"I am a string member\n";
}
You may have to use std::remove_reference.
You can use basic function overloading:
void something(const char*) { /* ... */ }
void something(int) { /* ... */ }
template <class P, class T>
void copyMemberToDocument(const P &childClass
std::string (T::*getter) (void) const) {
auto member = (childClass.*getter)();
something(member);
}

Call class method instide template class

I'm pretty new about template programming and I could not find any related question, sorry if already exists a similar question.
I have my template class
template<class T>
class MyTemplate
{
public:
virtual void set(const T& val) { value_ = val; }
virtual T get() const { return value_; }
// other stuff
private:
T value_;
}
and a custom class
class Foo
{
void bar();
}
Then I declare a variable
MyTemplate<Foo> var;
How can I call the bar() method from var ?
To call bar() you need an instance of Foo somewhere. As already mentioned, you could use inheritance. I see that the question has been edited to add such a member. You can't call members of the template type directly. You could add a wrapper in the MyTemplate, for instance 'doBar()'. You could also (though it's not a good idea) expose the Foo member by making it public.
#include <iostream>
template<class T>
class MyTemplate
{
public:
void doBar() { value_.bar(); }
public:
T value_;
};
class Foo
{
public:
void bar();
};
void Foo::bar()
{
std::cout << "Foo::bar()\n";
}
int main()
{
MyTemplate<Foo> var;
var.doBar();
var.value_.bar();
}
BTW any other old timers reminded of Swaine's Flames in Dr Dobbs journal?

Make variable class member outside of constructor

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.