Can virtual functions be C++20 coroutines? - c++20

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.

Related

how to do template class constructors as forward declaration

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.

Performance difference of defining a const at module level or function level

For constants such as string literals used as URLs that might be used multiple times by a function, which has better performance, defining them at module level, or inside the functions where they are used?
Module-level:
const URL = 'http://example.org';
function foo() {
return URL;
}
Function-level:
function foo() {
const url = 'http://example.org';
return url;
}
Strings are interned in common engines (definitely for literals at least), so it doesn't make any difference. Just write
function foo() {
return 'http://example.org';
}

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.

Passing list of arbitrary function arguments in Haxe

In ActionScript I can use ... in a function declaration so it accepts arbitrary arguments:
function foo(... args):void { trace(args.length); }
I can then call the function passing an array:
foo.apply(this, argsArray);
I'd like to call the function with arguments of unknown type and count. Is this possible in Haxe?
According to the Haxe documentation, you can use a Rest argument:
If the final argument of a macro is of type Array<Expr> the macro accepts an arbitrary number of extra arguments which are available from that array:
import haxe.macro.Expr;
class Main {
static public function main() {
myMacro("foo", a, b, c);
}
macro static function myMacro(e1:Expr, extra:Array<Expr>) {
for (e in extra) {
trace(e);
}
return macro null;
}
}
You could use Reflect.callMethod():
class Test {
static function main() {
var console = js.Browser.window.console;
var fn = console.log;
Reflect.callMethod(console, fn, [1, 2, "three", [4]]);
}
}
Starting with Haxe 4.2, Haxe will have native support for rest arguments:
function f(...args:Int) {
for (arg in args) {
trace(arg);
}
}
f(1, 2, 3);
...args:Int is simply syntax sugar for rest:haxe.Rest<Int>. Only the last argument of a function can be a rest argument.
You can also use ... to "spread" an array when calling a function with a rest argument:
final array = [1, 2, 3];
f(...array);
Just to add to this, if you're describing an extern for an external JavaScript library (or Python, Lua, or any target language that supports the rest parameter, e.g. ...rest), there is a specific Haxe type, haxe.extern.Rest, to express this.
Here's an example showing that the JavaScript Math.max function handles varargs: http://try.haxe.org/#4607C
class Test {
static function main() {
trace("JS Math.max takes varargs:");
trace(MyMath.max(1,2,3,4)); // 4
trace(MyMath.max(5,6)); // 6
}
}
#:native("Math")
extern class MyMath {
static function max(a:Float,
b:Float,
rest:haxe.extern.Rest<Float>):Float;
}
Note that the Haxe standard library does not define Math.max with Rest, as its goal is cross-platform compatibility.

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.