Having a template compile for only known execution path - c++

In the example below I am having a issue with getting it to compile even though I know the known execution path will be "safe". By "safe" I mean I know I will only use it in this manner. Is there an algorithm or a better way to structure a scenario where even though I know I will never have a "Type" of "float" passed with a "kind" value of 1?
The error in particular I get is that
error C2248: 'foo::foo' : cannot access private member declared in class 'foo'
Test case example
#include <vector>
using namespace std;
class foo {
private:
foo(float val) {
val = 99.0f;
}
public:
foo(int val) {
val = 2;
}
};
template<typename Type>
struct bar {
public:
vector<Type> array;
void Add(Type value) {
array.push_back(value);
}
};
class bunny {
bar<float> floats;
bar<foo> foos;
public:
template<typename Type>
void Initialize(int kind, Type value) {
if(kind == 0)
floats.Add(value);
else if(kind == 1)
foos.Add(value);
}
};
int main(void) {
bunny first; first.Initialize(0, 1.0f);
//bunny second; second.Initialize(1, 0);
return 0;
}

In C++ you can have multiple functions that have the same name but differ in number or type of the arguments, so, for example, you can have two functions:
void foo(float a)
{
std::cout << "Float!" << a << std::endl;
}
void foo(int a)
{
std::cout << "Int!" << a << std::endl;
}
If you call one of these functions the compiler will deduce what function to call based on the argument you gave to the function.
That is called function overloading.
In your case you could probably rewrite your bunny class to something like this:
class bunny {
bar<float> floats;
bar<foo> foos;
public:
void Initialize(foo value) {
foos.Add(value);
}
void Initialize(float value) {
floats.Add(value);
}
};
If you call first.Initialize(1.0f) the compiler knows that he needs to call void Initialize(float value) because you passed a float to the function.

Related

How can I return an arbitrary derived class of an abstract generic class and call its generic methods?

I've got an abstract class that uses variable template.
template <class T>
class Abstract
{
public:
virtual void print(T t) = 0;
};
There can be any derivatives of the class like so:
class A : public Abstract<std::string>
{
public:
void print(std::string str)
{
std::cout << str << std::endl;
}
};
class B : public Abstract<int>
{
public:
void print(int number)
{
std::cout << std::to_string(number) << std::endl;
}
};
Now I want a function to return one of these derivatives so I can execute the print method. And here is my Problem:
template (class T); // error here
Abstract<T> &f(int n) // what should the return type look like?
{
if (n == 0)
{
A a{};
return a;
}
else
{
B b{};
return b;
}
}
int main()
{
A a{f(0)};
a.print("foo");
B b{f(1)};
b.print(42);
return 0;
}
So how is it be possible to return a class with unknown parameter type and call its methods?
I already tried returning derived classes without templates which works fine. As soon as templates are added code wont compile. I also tried void* and reinterpret_cast. Problem here is that I have manually to decide to what type to cast to.
So how can I return an arbitrary superclass of an abstract generic class and call its generic methods?
I think inheritance is the wrong approach here. Instead I would use specialization instead:
template<typename T>
struct Foo;
template<>
struct Foo<std::string>
{
void print(std::string const& s)
{
std::cout << s << '\n';
}
};
template<>
struct Foo<int>
{
void print(int value)
{
std::cout << value << '\n';
}
};
Then you don't need a selector to pick the object to create, just the correct type:
int main()
{
Foo<std::string> f1;
f1.print("hello");
Foo<int> f2;
f2.print(123);
}
If you really need a factor function, then it could be created like this:
template<typename T>
Foo<T> create()
{
return Foo<T>();
}
And use like
int main()
{
auto f1 = create<std::string>();
f1.print("hello");
auto f2 = create<int>();
f2.print(123);
}

Check for template type parameter, during compile time, for type specific operation

First of all, the code is restricted to C++11, so I cannot make use of if constexpr
Following is my sample code snippet:
class A{
public:
int a;
int b;
}
class B{
public:
int key;
int val;
}
class C{
public:
int n1;
int n2;
}
class D{
public:
int n1;
int n2;
}
class E{
public:
int n1;
int n2;
}
template<typename T>
void func1(T data) {
if (T == type(A)) { // Just pseudo template-check code
std::cout<<data.a<<data.b; //<------1
} else if (T == type (B)) { // Just pseudo template-check code
std::cout<<data.key<<data.val; //<------2
} else {
std::cout<<data.n1<<data.n2; //<------3
}
int main() {
A a;
B b;
C c;
D d;
E e;
func1(a);
func1(b);
func1(c);
func1(d);
func1(e);
return 0;
}
Currently, I get a compile-time error at,
1: B,D,E,F has no member a & b
&
2: A,D,E,F has no member key & val
&
3. A, B has no member n1 & n2
I tried using is_same() & also this, but I get same compile time error every time.
I cannot make use of C++14/C++17
How could I make use of specialized template functions?
Edited the code to highlight the need of a template.
You can use a function overload and avoid the function template altogether.
void func1(A a)
{
// Type dependent code.
}
void func1(B a)
{
// Type dependent code.
}
A function template makes sense only if there is common code for all the types for which the function call is made. If you have some code that is common to all types and some code that are type dependent, then you can use:
void func1(A a)
{
// Type dependent code.
}
void func1(B a)
{
// Type dependent code.
}
template <typename T>
void func2(T t)
{
// Type independent code.
}
template <typename T>
void func(T obj)
{
func1(obj); // Call function that uses type dependent code.
func2(obj); // Call function that uses type independent code.
}
You must write specializations of the function for the two types your want to use it with.
#include<iostream>
class A{
public:
int a;
int b;
};
class B{
public:
int key;
int val;
};
template<typename T>
void func1(T);
template<>
void func1<A>(A arg) {
std::cout<<"A"<<std::endl;
std::cout<<arg.a<<arg.b;
}
template<>
void func1<B>(B arg) {
std::cout<<"B"<<std::endl;
std::cout<<arg.key<<arg.val;
}
int main(){
A a;
func1(a);
B b;
func1(b);
}
Simple overload does the job.
template <typename T>
void func1(T data)
{
std::cout << data.n1 << data.n2;
}
void func1(A data)
{
std::cout << data.a << data.b;
}
void func1(B data)
{
std::cout << data.key << data.val;
}
https://godbolt.org/z/r7Ee6E
Tweaked a bit: https://godbolt.org/z/xxPWaE

Access Member Variables using templates

I need a template function that can serve generic purpose of accessing a member variable and operating functions present in that member variable. I have a set of functions to be called and this will solve my purpose.
I have tried the following
class Utilities {
public:
template<typename Container, typename MemberVar, typename Operator>
static void for_all(Container& C, MemberVar memvar, Operator Op) {
for (auto& element : C) {
(element.memvar->Op)();
}
}
};
I have the following test code where there is class Test that has PrivateImpl and DataStructure holding that privatimpl.
Below is the print function that calls the Utilities::for_all function with privateimpl's print function
void Test::print() {
::Utilities::for_all(m_vec_struct_privateimpl,&Test::Struct_PrivateImpl::m_privateimpl,&Test::CPrivateImpl::print);
}
Below is the details about all the classes
// Main Class
class Test {
public:
Test();
~Test();
void print();
private:
class CPrivateImpl;
struct Struct_PrivateImpl;
std::vector<Struct_PrivateImpl> m_vec_struct_privateimpl;
}; //class Utilities
// Class PrivateImpl
class Test::CPrivateImpl {
public:
CPrivateImpl(std::initializer_list<int>& lst) {
for (auto& i : lst) {
m_vec_int.push_back(i);
}
}
void print(int i) {
cout << i << " ";
}
private:
std::vector<int> m_vec_int;
}; //class Test::CPrivateImpl
// Data Structure having PrivateImpl
struct Test::Struct_PrivateImpl {
public:
Struct_PrivateImpl(int i) {
m_privateimpl = std::make_shared<Test::CPrivateImpl>(std::initializer_list<int>{100+i,200+i,300+i});
};
~Struct_PrivateImpl() {
}
//private:
std::shared_ptr<CPrivateImpl> m_privateimpl;
}; // class WiperSkeletonSomeIP::Struct_PrivateImpl
Test::Test(){
for(auto i = 0u; i != 3; ++i) {
Struct_PrivateImpl a_struct_pvtimpl(i);
m_vec_struct_privateimpl.push_back(a_struct_pvtimpl);
}
}
void Test::print() {
::Utilities::for_all(m_vec_struct_privateimpl,&Test::Struct_PrivateImpl::m_privateimpl,&Test::CPrivateImpl::print);
}
// This is the main function
int main() {
Test t;
t.print();
}
I am getting error message saying memvar has function Op.
This is an example code I have a lot of functions to be called within PrivateImpl class.
Please help me how to solve this.
Syntax to acces via member pointer is .* or ->*:
class Utilities {
public:
template <typename Container, typename MemberVar, typename Operator>
static void for_all(Container& C, MemberVar memvar, Operator Op)
{
for (auto& element : C) {
((*(element.*memvar)).*Op)();
}
}
};
Demo

SFINAE and number of parameters

I have a template class C<T> which I intend to instantiate with T as some other classes A and B. C<T> has a method foo whose signature I would like to depend on whether T was instantiated as A or B. For example, consider the following code:
#include <iostream>
#include <string>
class A {
public:
void message() {
std::cout << "message with no args" << std::endl;
}
};
class B {
public:
void message(int x) {
std::cout << "message with " << x << std::endl;
}
};
template<typename T>
class C {
private:
T internal;
public:
C(T& x) {
internal = x;
}
void call() {
internal.message();
}
void call(int x) {
internal.message(x);
}
};
int main(int argc, char* argv[]) {
A a;
B b;
C<A> ca(a);
C<B> cb(b);
ca.call();
cb.call(42);
// ca.call(42); ERROR HERE
return 0;
}
This runs correctly. ca.call(42) would raise a compilation error because there is no method A::message(int). However, if I for some reason introduce a method A::message(int) in A, the code may allow calling ca.call(42), which I would like to prevent.
I know that SFINAE techniques would allow to declare a method C::call(T::call_type x) where T::call_type would be a typedef for each intended instantiation of T. However, this only allows me to change the type of the argument of C::call. I would like instead to make the signature (in particular, the number of parameters) of C::call on T. I would thus prevent ca.call(42) from being a valid call even if there is a method A::message(int) in A.
Is there any way to do this?
I don't know all the ins and outs of SFINAE, but what do you think of this?
template <
typename = std::enable_if_t<std::is_same<std::decay_t<T>, A>::value>>
void call() {
internal.message();
}
template <
typename = std::enable_if_t<std::is_same<std::decay_t<T>, B>::value>>
void call(int x) {
internal.message(x);
}
You can use == false too
template <
typename = std::enable_if_t<std::is_same<std::decay_t<T>, B>::value == false>>
You can do this with template specializations:
// Main template used by every other type T.
template<typename T>
class C; // or some other implementation.
// This gets used for T = A.
template<>
class C<A> {
private:
A internal;
public:
C(A& x) {
internal = x;
}
void call() {
internal.message();
}
};
// This gets used for T = B.
template<>
class C<B> {
private:
B internal;
public:
C(B& x) {
internal = x;
}
void call(int x) {
internal.message(x);
}
};
If you don't like that you need to duplicate some common code, then you can have a base class with all those common things and inherit from it in each specialization.

C++ templates and function resolution

Here is a problem I stumbled accross when refactoring some code and I was wondering if there is a better way to do it:
#include <iostream>
template<typename T>
class Foo
{
public:
Foo()
{
init(x);
}
T x;
};
void init(int& i)
{
i = 42;
}
int main()
{
Foo<int> foo;
std::cout << foo.x << std::endl;
return 0;
}
Unfortunately, this doesn't compile - neither with GCC or with Clang. The function init called in Foo's constructor is not declared. In this toy example, this could be solved by moving the function itself ahead of the template. However, in a more complex context, this may not work. Originally, I intended to use overloads of init to allow some setup for the classes used in the template.
I assumee that in this context init is a non-dependend name - even though the argument of the function call depends on the template parameter (which was odd for me at first). Is there a way to trick it to also consider function definitions defined after the template itself?
I know that I can use template specialization (which was in the original code in the first place, but I wanted to replace it with simpler overloads):
template<typename>
struct Initializer;
template<>
struct Initializer<int>
{
static void init(int& i)
{
i = 42;
}
}
Is there a way to make this work with function overloads as well? I know, boost::serialization also relies on function overloads for custom types, but I did not really find where and how they implemented that.
You can solve the ordering problem by calling through a template function object - in the same way that boost::hash finds the ADL-function hash_value(x).
This works because the expansion of the template is deferred until the point of first use:
#include <iostream>
namespace A {
struct XX {
friend void init(XX&);
};
}
namespace B {
struct YY {
friend void init(YY&);
};
}
/// default case - call init on T found by ADL
template<class T>
struct call_init
{
void operator()(T& o) const {
init(o);
}
};
template<typename T>
class Foo
{
public:
Foo()
{
auto initialiser = call_init<decltype(this->x)>();
initialiser(this->x);
}
T x;
};
void init(int& x) {
x = 2;
}
// special case, initialise an int
template<> struct call_init<int>
{
void operator()(int& x) const {
init(x);
}
};
int main()
{
Foo<int> foo;
Foo<A::XX> foox;
Foo<B::YY> fooy;
std::cout << foo.x << std::endl;
return 0;
}
Your problem is also that intis not a class and no ADL is done for it, replacing int by custom class works:
template<typename T>
class Foo
{
public:
Foo() { init(x); }
T x;
};
struct C
{
int i = 0;
};
void init(C& c) { c.i = 42; }
Demo.
To allow to works for primitive type as int, you have to introduce some custom type:
template <typename> struct tag {};
template<typename T>
class Foo
{
public:
Foo() { init(x, tag<T>{}); }
T x;
};
void init(int& i, tag<int>) { i = 42; }
Demo