how to do template class constructors as forward declaration - c++20

I am migrating my code from c++17 to c++20 and need to use require instead of std::enable_if...
How to define class constructors as forward declaration with c++20 that uses require keyword on following sample ?
#include <type_traits>
class CChMyBaseClass {
};
template <
typename _ChClass,
typename _ChFunction>
class CChMyClass : public CChMyBaseClass {
private:
_ChFunction m_ChFunction;
public:
// how to do forward declaration ?
CChMyClass()
requires (std::is_member_function_pointer<_ChFunction>::value)
: CChMyBaseClass() {
}
// how to do forward declaration ?
CChMyClass()
requires (!std::is_member_function_pointer<_ChFunction>::value)
: CChMyBaseClass()
, m_ChFunction(
nullptr) {
}
};
class CChTestClass {
public:
void ChTest() {
}
};
void ChTest() {
}
int main() {
CChMyClass<CChTestClass, decltype(&CChTestClass::ChTest)> CChMyClass1();
CChMyClass<CChTestClass, decltype(&ChTest)> CChMyClass2();
return 0;
}

It's really not different from any other type of forward declaration. Just write:
template <typename _ChClass, typename _ChFunction>
class CChMyClass: public CChMyBaseClass {
...
CChMyClass() requires (std::is_member_function_pointer<_ChFunction>::value);
CChMyClass() requires (!std::is_member_function_pointer<_ChFunction>::value);
...
};
I think the difficulty is rather in the actual function definitions. But even that is not too difficult if you think about it. You just need to include the template parameters and the requires clause again:
template <typename _ChClass, typename _ChFunction>
CChMyClass<_ChClass, _ChFunction>::CChMyClass()
requires (std::is_member_function_pointer<_ChFunction>::value)
: CChMyBaseClass(), m_ChFunction(...) {
...
};
Note that in your example, you did not declare two instances of CChMyClass in main(), but rather forward declared two functions that had a CChMyClass as a return type (this is known as the most vexing parse). Just omit the () at the end, or use braces instead.

Related

Can virtual functions be C++20 coroutines?

The title says it all: Can virtual functions also be C++20 coroutines?
struct A {
virtual std::generator<int> generate() const = 0; // std::generator: C++23
};
struct B : A {
virtual std::generator<int> generate() const { ~~~~ }
};
?
Yes.
From cppreference
Restrictions
Coroutines cannot use variadic arguments, plain return statements, or placeholder return types (auto or Concept).
Constexpr functions, constructors, destructors, and the main function cannot be coroutines.
Knowing how they work, I don't see any reason why it wouldn't be allowed.

How to get the underlying vector of an IVector<IInspectable>

I want to use a function that requires me to pass to it as a parameter a void pointer to beginning of a block of memory. The data has to be contiguous in memory for this function to work correctly.
Right now my data is stored in a IVector<IInspectable>. Looking at the memory layout of this IVector in the debugger I see that there is 28 bytes between my data. Which I think are the 7 function pointers from IUnknown and IInspectable. How can I get the underlying contiguous memory allocation of my data?
UPDATE:
Here is the solution I came up with.
Instead of using the IVector<IInspectable> I created a custom vector using the winrt::vector_base as recommended here: https://learn.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/collections
and I wrapped it in a windows runtime component so that I can use this custom vector from C#.
It looks like this:
MyVector.idl
namespace RuntimeComponent1
{
[default_interface]
runtimeclass MyVector
{
MyVector();
void Append(IInspectable in_val);
}
}
MyVector.h
// MyVector.h
#pragma once
#include "MyVector.g.h"
namespace winrt::RuntimeComponent1::implementation
{
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Collections;
struct _MyVector :
implements<_MyVector, IVector<int>, IVectorView<int>, IIterable<int>>,
winrt::vector_base<_MyVector, int>
{
auto& get_container() const noexcept
{
return m_values;
}
auto& get_container() noexcept
{
return m_values;
}
private:
std::vector<int> m_values{};
};
struct MyVector : MyVectorT<MyVector, _MyVector>
{
MyVector() = default;
void Append(Windows::Foundation::IInspectable const& in_val);
};
}
namespace winrt::RuntimeComponent1::factory_implementation
{
struct MyVector : MyVectorT<MyVector, implementation::MyVector>
{
};
}
MyVector.cpp
#include "pch.h"
#include "MyVector.h"
using namespace winrt;
namespace winrt::RuntimeComponent1::implementation
{
void MyVector::Append(Windows::Foundation::IInspectable const& in_val)
{
base_type::Append(winrt::unbox_value<int>(in_val));
}
}
Example usage:
C#
MyRuntimeComponent.MyVector my_vec = new RuntimeComponent1.MyVector();
my_vec.Append(2);
my_vec.Append(4);
MyRuntimeComponent.MyControl my_control = new RuntimeComponent0.MyControl();
my_control.do_stuff_with_contiguous_memory(my_vec);
C++
void MyControl::do_stuff_with_contiguous_memory(RuntimeComponent1::MyVector const& in_data)
{
// Yay data is contiguous
auto contiguous_data = in_data.as<MyVector>()->get_container().data();
}
The end result is that I can pass data from C# to C++/WinRT and the data will be contiguous in C++, which fixes my original problem. It works but I wonder if there might be a simpler / better way?

How to initialize c++/cx class with aggregate initialization?

I have this ref class:
namespace N
{
public ref class S sealed
{
public:
property Platform::String^ x;
};
}
How do I initialize it in place with the aggregate initializer?
I have tried:
N::S s1 = { %Platform::String(L"text") };
but the compiler says
error C2440: 'initializing': cannot convert from 'initializer list' to
'N::S'
Also:
N::S s1 { %Platform::String(L"text") };
and the error is:
error C2664: 'N::S::S(const N::S %)': cannot convert argument 1 from
'Platform::String ^' to 'const N::S %'
This works greatly with the standard c++ like this:
struct T
{
wstring x;
};
T x { L"test" };
I do not want to use a constructor here.
I assume you mean you don't want a public constructor on the projected WinRT type -- no problem, you can use the internal keyword to mean "public inside C++ but not exposed through interop". That means you can even use native C++ types for your parameters if you like:
namespace Testing
{
public ref class MyTest sealed
{
public:
property String^ Foo {
String^ get() { return m_foo; }
void set(String^ value) { m_foo = value; }
}
internal:
// Would not compile if it was public, since wchar_t* isn't valid
MyTest(const wchar_t* value) { m_foo = ref new String(value); }
private:
String^ m_foo;
};
}
MainPage::MainPage()
{
// Projected type does NOT have this constructor
Testing::MyTest t{ L"Hello" };
OutputDebugString(t.Foo->Data());
t.Foo = "\nChanged";
OutputDebugString(t.Foo->Data());
}
Also you don't need to have the private variable to hold the string -- you could just use the auto-property as in your original code -- but I prefer to be explicit. It also means that if you needed to access the string a lot from within your C++ code you could provide an internal accessor function and not have to go through a vtable call to get at it.

C++ boost::bind and boost::function, class member function callbacks and operator==. What am I doing wrong?

I've got a problem with using boost::bind and boost::function and passing boost::function as a callback into another class.
Here's an example that is the problematic situation:
typedef boost::function<void (bool)> callbackFunction;
class HasCallback
{
public:
HasCallback() : value(0)
{
}
int value;
void CallBackFunction(bool changed)
{
std::cout << "HasCallback class. CallBackFunction called. Parameter: " << value << std::endl;
}
};
class ReceivesCallback
{
public:
void AddCallback(callbackFunction newFunc)
{
callbacks.push_back(newFunc);
}
void execute(int &i)
{
for(std::vector<callbackFunction>::iterator it = callbacks.begin(); it != callbacks.end(); it++)
{
(*it)(i++);
}
}
void RemoveHandler(callbackFunction oldFunc)
{
for(std::vector<callbackFunction>::iterator it = callbacks.begin(); it != callbacks.end(); it++)
{
if((*it) == oldFunc)
{
callbacks.erase(it);
break;
}
}
}
private:
std::vector<callbackFunction> callbacks;
};
int main()
{
HasCallback hc;
ReceivesCallback rc;
rc.AddCallback(boost::bind(&HasCallback::CallBackFunction, &hc, _1));
hc.value = 123;
HasCallback hc2;
rc.AddCallback(boost::bind(&HasCallback::CallBackFunction, &hc2, _1));
hc2.value = 321;
int a = 0;
rc.RemoveHandler(boost::bind(&HasCallback::CallBackFunction, &hc2, _1));
rc.execute(a);
}
The problem I'm having is that this doesn't even compile. It fails within ReceivesCallback::RemoveHandler in the if((*it) == oldFunc) line with the error saying that there's more than one overload of the operator== for the thing i'm trying to do.
I keep searching for this and can't find what I'm doing wrong. Also, I keep finding contradicting information, one saying that it's possible to compare boost::function-s and another saying it's not. I can see the operator== functions within boost/function_base.hpp and i believe this is supposed to work, I just can't seem to figure out how. Can someone help me out here? My suspicion is that it fails because the parameters of the boost::bind need to be specified fully(be concrete values) but this is something i cannot get in the code I'm developing, I just need to know whether the passed handler is registered or not, since I'm binding to an object it should have all the information neeeded to make the distinction.
See Boost.Function FAQ for an explanation : Why can't I compare boost::function objects with operator== or operator!= ?.
Boost.Functions only provides comparison of a boost::function with an arbitrary function object. I believe that making your RemoveHandler member function template could fix the issue :
template<class Functor>
void RemoveHandler(const Functor &oldFunc)
{
for(std::vector<callbackFunction>::iterator it = callbacks.begin(); it != callbacks.end(); it++)
{
if((*it) == oldFunc)
{
callbacks.erase(it);
break;
}
}
}
Here, oldFunc gets to keep its actual type without being 'wrapped' in a boost::function.

std::vector of std::function

I have the following:
typedef std::function<void(const EventArgs&)> event_type;
class Event : boost::noncopyable
{
private:
typedef std::vector<event_type> EventVector;
typedef EventVector::const_iterator EventVector_cit;
EventVector m_Events;
public:
Event()
{
}; // eo ctor
Event(Event&& _rhs) : m_Events(std::move(_rhs.m_Events))
{
}; // eo mtor
// operators
Event& operator += (const event_type& _ev)
{
assert(std::find(m_Events.begin(), m_Events.end(), _ev) == m_Events.end());
m_Events.push_back(_ev);
return *this;
}; // eo +=
Event& operator -= (const event_type& _ev)
{
EventVector_cit cit(std::find(m_Events.begin(), m_Events.end(), _ev));
assert(cit != m_Events.end());
m_Events.erase(cit);
return *this;
}; // eo -=
}; // eo class Event
And during compilation:
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(41): error C2451: conditional expression of type 'void' is illegal
1> Expressions of type void cannot be converted to other types
Now, I understand this is because of what is being stored in the vector and the operator ==. Is there another way to store std::function in an STL container? Do I need to wrap it up in something else?
You can store boost::function in the vector, provided you don't use std::find. Since you seem to need this, wrapping the function in its own class with equality would be probably the best.
class EventFun
{
int id_;
boost::function<...> f_;
public:
...
bool operator==(const EventFun& o) const { return id_==o.id_; } // you get it...
};
Note that this requires you maintain the id_ in a sane way (eg. two different EventFuns will have different id_s, etc.).
Another possibility would be to store boost::functions with a tag the client would remember and use to identify the particular function on deleting it.