I am new authoring C++/WinRT runtime classes, and I was requested to overload the subscript operator ([ ]) for a runtime class Parameter. The class Parameter contains an IMap<hstring, IInspectable> that stores a set of parameters indexed by the parameter name.
Here is the code:
namespace winrt::Parameter::implementation
{
using namespace winrt;
using namespace Windows::Foundation::Collections;
struct Parameter : ParameterT<Parameter>
{
private:
IMap<hstring, IInspectable> m_Parameters{ nullptr };
public:
Parameter() { m_Parameters = single_threaded_map<hstring, IInspectable>(); }
~Parameter() {};
IInspectable& operator[](const hstring& key)
{
if (!m_Parameters.HasKey(key))
{
m_Parameters.Insert(key, {});
}
return m_Parameters.Lookup(key);
}
IInspectable const& operator[](const hstring& key) const
{
if (!m_Parameters.HasKey(key))
{
m_Parameters.Insert(key, {});
}
return m_Parameters.Lookup(key);
}
};
}
namespace winrt::Parameter::factory_implementation
{
struct Parameter : ParameterT<Parameter, implementation::Parameter>
{
};
}
The code above compiles with no errors, but I get the below error when I try to consume the Parameter code in a UWP C# test App:
Parameter parameter = new Parameter();
const string V = "test";
parameter[V] = "any test value";
string test = parameter[V];
Error CS0021 Cannot apply indexing with [ ] to an expression of type 'Parameter'
Does anyone have any ideas on what I am missing here?
The problem seems to be with the C++/WinRT version because this other similar code using standard C++/17 works as expected.
class Parameter
{
private:
std::map<std::string, std::any> m_Parameter{};
public:
std::any& operator[](const std::string& name);
};
std::any& Parameter::operator[](const std::string& key)
{
if (m_Parameter.find(key) == m_Parameter.end())
{
m_Parameter.insert({ key, {} });
}
return m_Parameter.at(key);
}
int main()
{
Parameter parameter{};
parameter["test"] = 'b';
parameter["other test"] = std::string("other test value");
std::cout << std::any_cast<std::string>(parameter["other test"]) << '\n';
std::cout << std::any_cast<char>(parameter["test"]) << '\n';
return 0;
}
Related
Why is Assert::AreSame() failing?
C++ class to be tested:
template <typename T>
class XPtr
{
private:
T* p;
public:
XPtr(T* ptr) {
p = ptr;
}
XPtr(const XPtr& ptr) {
p = ptr.p;
}
T* operator&() {
return p;
}
// The following declaration compiles but still
// is it the correct way of declaring friend function?
template<typename T>
friend std::wstring getString(const XPtr<T>& p);
};
template<typename T>
std::wstring getString(const XPtr<T>& p) {
std::wstringstream ss;
ss << L"{" << p.p;
if (p.p != 0) { ss << L"," << *p.p; }
ss << L"}";
return ss.str();
}
Native C++ Unit Test is as follows:
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace Microsoft {
namespace VisualStudio {
namespace CppUnitTestFramework {
//Actually I would like to specialize for XPtr<T> instead of XPtr<int>,
//how to do it?
template<>
static std::wstring ToString<XPtr<int> >(const class XPtr<int> & t)
{ return getString<int>(t); }
}
}
}
namespace TestRCPtr1
{
TEST_CLASS(UnitTest1)
{
public:
TEST_METHOD(TestMethod6)
{
XPtr<int> p1(new int(1));
XPtr<int> p2(p1);
Assert::AreEqual(&p1, &p2); // Test passes
Assert::AreSame(p1, p2); // Test fails, see below for error message
}
};
}
Result Message: Assert failed. Expected:<{000000001BE465D0,1}> Actual:<{000000001BE465D0,1}>
Question 1: As per my understanding Assert::AreSame() should compare with logic &p1==&p2 and pass successfully. What is going wrong here?
Question 2: How to specialize Microsoft::VisualStudio::CppUnitTestFramework::ToString() (see at top of unit test code) for XPtr<T> instead of XPtr<int> ?
I have two classes and depending on the nature of key, I would like to get the struct value out of the boost::variant. The code is listed below.
#include <iostream>
#include <boost/variant.hpp>
using namespace std;
class A {
public:
struct greeting {
string hello;
};
class B {
public:
struct greeting {
string bye;
};
};
typedef boost::variant<A::greeting, B::greeting> greet;
greet getG(string key) {
greet g;
if (key == "A") {
g.hello = "MY ENEMY"; // this line doesn't work
}
else {
g.bye = "MY FRIEND"; // nor this line
}
return g;
};
int main() {
A a;
B b;
greet h = getG("A");
A::greeting my = boost::get<A::greeting>(h);
cout << my.hello << endl;
return 0;
}
The exact error that I am getting is:
error: no member named 'hello' in 'boost::variant<A::greeting, B::greeting, boost::detail::variant::void_, boost::detail::variant::void_, ...>' g.hello = "MY ENEMY"; and
error: no member named 'bye' in 'boost::variant<A::greeting, B::greeting, .../>' g.bye = "MY FRIEND";
Any help is appreciated.
The variant type doesn't have the .hello and .bye members. You can access them via a "visitor" function. But you still have to decide what to do when the visitor is not applied to the right type. I think you are not using Boost.Variant in the way that is intended to be used. (For example the conditionals don't smell well).
http://www.boost.org/doc/libs/1_61_0/doc/html/variant/reference.html#variant.concepts.static-visitor
struct hello_visitor : boost::static_visitor<>{
string const& msg;
hello_visitor(string const& msg) : msg(msg){}
void operator()(A::greeting& t) const{
t.hello = msg;
}
void operator()(B::greeting& t) const{
// throw? ignore? other?
}
};
struct bye_visitor : boost::static_visitor<>{
string const& msg;
bye_visitor(string const& msg) : msg(msg){}
void operator()(A::greeting& t) const{
// throw? ignore? other?
}
void operator()(B::greeting& t) const{
t.bye = msg;
}
};
greet getG(string key) {
greet g;
if (key == "A") { // is "key" handling the type, if so you can delegate this to the library instead of doing this.
boost::apply_visitor(hello_visitor("MY ENEMY"), g);
}
else {
boost::apply_visitor(bye_visitor("MY FRIEND"), g);
}
return g;
};
As far as I know, this seems to be impossible in a straightforward way. Making the member const makes it const for everyone. I would like to have a read-only property, but would like to avoid the typical "getter". I'd like const public, mutable private. Is this at all possible in C++?
Currently all I can think of is some trickery with templates and friend. I'm investigating this now.
Might seem like a stupid question, but I have been surprised by answers here before.
A possible solution can be based on an inner class of which the outer one is a friend, like the following one:
struct S {
template<typename T>
class Prop {
friend struct S;
T t;
void operator=(T val) { t = val; }
public:
operator const T &() const { return t; }
};
void f() {
prop = 42;
}
Prop<int> prop;
};
int main() {
S s;
int i = s.prop;
//s.prop = 0;
s.f();
return i, 0;
}
As shown in the example, the class S can modify the property from within its member functions (see S::f). On the other side, the property cannot be modified in any other way but still read by means of the given operator that returns a const reference to the actual variable.
There seems to be another, more obvious solution: use a public const reference member, pointing to the private, mutable, member. live code here.
#include <iostream>
struct S {
private:
int member;
public:
const int& prop;
S() : member{42}, prop{member} {}
S(const S& s) : member{s.member}, prop{member} {}
S(S&& s) : member(s.member), prop{member} {}
S& operator=(const S& s) { member = s.member; return *this; }
S& operator=(S&& s) { member = s.member; return *this; }
void f() { member = 32; }
};
int main() {
using namespace std;
S s;
int i = s.prop;
cout << i << endl;
cout << s.prop << endl;
S s2{s};
// s.prop = 32; // ERROR: does not compile
s.f();
cout << s.prop << endl;
cout << s2.prop << endl;
s2.f();
S s3 = move(s2);
cout << s3.prop << endl;
S s4;
cout << s4.prop << endl;
s4 = s3;
cout << s4.prop << endl;
s4 = S{};
cout << s4.prop << endl;
}
I like #skypjack's answer, but would have written it somehow like this:
#include <iostream>
template <class Parent, class Value> class ROMember {
friend Parent;
Value v_;
inline ROMember(Value const &v) : v_{v} {}
inline ROMember(Value &&v) : v_{std::move(v)} {}
inline Value &operator=(Value const &v) {
v_ = v;
return v_;
}
inline Value &operator=(Value &&v) {
v_ = std::move(v);
return v_;
}
inline operator Value& () & {
return v_;
}
inline operator Value const & () const & {
return v_;
}
inline operator Value&& () && {
return std::move(v_);
}
public:
inline Value const &operator()() const { return v_; }
};
class S {
template <class T> using member_t = ROMember<S, T>;
public:
member_t<int> val = 0;
void f() { val = 1; }
};
int main() {
S s;
std::cout << s.val() << "\n";
s.f();
std::cout << s.val() << "\n";
return 0;
}
Some enable_ifs are missing to really be generic to the core, but the spirit is to make it re-usable and to keep the calls looking like getters.
This is indeed a trickery with friend.
You can use curiously recurring template pattern and friend the super class from within a property class like so:
#include <utility>
#include <cassert>
template<typename Super, typename T>
class property {
friend Super;
protected:
T& operator=(const T& val)
{ value = val; return value; }
T& operator=(T&& val)
{ value = val; return value; }
operator T && () &&
{ return std::move(value); }
public:
operator T const& () const&
{ return value; }
private:
T value;
};
struct wrap {
wrap() {
// Assign OK
prop1 = 5; // This is legal since we are friends
prop2 = 10;
prop3 = 15;
// Move OK
prop2 = std::move(prop1);
assert(prop1 == 5 && prop2 == 5);
// Swap OK
std::swap(prop2, prop3);
assert(prop2 == 15 && prop3 == 5);
}
property<wrap, int> prop1;
property<wrap, int> prop2;
property<wrap, int> prop3;
};
int foo() {
wrap w{};
w.prop1 = 5; // This is illegal since operator= is protected
return w.prop1; // But this is perfectly legal
}
Is it possible to automatically wrap a value in a temporary whose lifetime extends across the entire statement?
Originally I hoped a solution or alternative to my problem would present itself while writing the details for the question, unfortunately that didn't happen, so...
I have an abstract base class Logger that provides a streaming-like interface for generating log statements. Given an instance logger of this class, I want the following to be possible:
logger << "Option " << variable << " is " << 42;
Unlike regular streams, which simply generate a string from all the components (4 components in the example above), I want to generate an instance of a class Statement that manages a linked list of all the statement's components. The entire statement is then passed via pure virtual method to a class derived from Logger, which can iterate over all the components of the statement and do whatever with them, including obtaining information about their type, retrieving their value, or converting them to a string.
The tricky bit: I want to do the above without dynamic memory allocations. This means that every component of the statement must be wrapped by a temporary type that links the components into a traversable list, within the scope of the statement!
I posted a working example on ideone, with one problem: every component needs to be wrapped by a function call in order to generate an instance of the temporary type. The log statement therefore ends up looking like this:
logger << wrap("Option ") << wrap(variable) << wrap(" is ") << wrap(42);
All my attempts to get rid of the wrap function (e.g., using an implicit converting constructor for the component), have failed thus far, therefore this question.
How can the components of the log statement automatically be wrapped in their component type (e.g., using a converting constructor for the component), without the need for an explicit call to a wrapping function?
Alternatively, I would appreciate suggestions for other ways that achieve the same effect, i.e., allowing iteration over the components of the log statement in a class derived from logger, without dynamic memory allocations.
Reference: Full code on ideone:
#include <iostream>
#include <sstream>
struct Statement;
struct Logger;
struct ComponentBase;
//------------------------------------------------------------------------------
struct ComponentBase {
mutable ComponentBase *next;
ComponentBase() : next(nullptr) { }
virtual std::string toString() = 0;
};
template <typename T>
struct Component : ComponentBase {
T value;
Component(T value) : value(value) { }
~Component() { }
virtual std::string toString() {
std::stringstream ss;
ss << value;
return ss.str();
}
};
struct ComponentIterator {
ComponentBase *ptr;
ComponentIterator(ComponentBase *ptr) : ptr(ptr) { }
ComponentBase &operator*() { return *ptr; }
void operator++() { ptr = ptr->next; }
bool operator!=(ComponentIterator &other) { return (ptr != other.ptr); }
};
//------------------------------------------------------------------------------
struct Statement {
Logger *logger;
ComponentBase *front;
ComponentBase *back;
ComponentIterator begin() { return front; }
ComponentIterator end() { return nullptr; }
template <typename T>
Statement(Logger &logger, Component<T> &component)
: logger(&logger), front(&component), back(&component) { }
~Statement();
template <typename T>
Statement &operator<<(Component<T> &&component) {
back->next = &component;
back = &component;
return *this;
}
};
//------------------------------------------------------------------------------
struct Logger {
template <typename T>
Statement operator<<(Component<T> &&component) {
return {*this, component};
}
virtual void log(Statement &statement) = 0;
};
Statement::~Statement() {
logger->log(*this);
}
//------------------------------------------------------------------------------
template <typename T>
Component<T const &> wrap(T const &value) {
return value;
}
template <size_t N>
Component<char const *> wrap(char const (&value)[N]) {
return value;
}
//------------------------------------------------------------------------------
struct MyLogger : public Logger {
virtual void log(Statement &statement) override {
for(auto &&component : statement) {
std::cout << component.toString();
}
std::cout << std::endl;
}
};
int main() {
std::string variable = "string";
MyLogger logger;
logger << wrap("Option ") << wrap(variable) << wrap(" is ") << wrap(42);
}
I have some crazy but working solution.
Having component implemented like this you will get rid of templates all over your code:
struct Component
{
mutable Component *next;
typedef std::function<std::string()> ToStringFunction;
ToStringFunction toString; // <-- 1
template<typename T>
Component(const T& value)
: next(nullptr),
toString(nullptr)
{
toString = [&value](){
std::stringstream ss;
ss << value;
return ss.str();
};
}
};
Where (1) is the unction that knows what to do. This member std::function is a space for optimization.
And the rest of the code should look like:
struct ComponentIterator {
Component *ptr;
ComponentIterator(Component *ptr) : ptr(ptr) { }
Component &operator*() { return *ptr; }
void operator++() { ptr = ptr->next; }
bool operator!=(ComponentIterator &other) { return (ptr != other.ptr); }
};
//------------------------------------------------------------------------------
struct Statement {
Logger *logger;
Component *front;
Component *back;
ComponentIterator begin() { return front; }
ComponentIterator end() { return nullptr; }
Statement(Logger &logger, Component &component)
: logger(&logger), front(&component), back(&component) { }
~Statement();
Statement &operator<<(Component &&component) {
back->next = &component;
back = &component;
return *this;
}
};
//------------------------------------------------------------------------------
struct Logger {
Statement operator<<(Component &&component) {
return{ *this, component };
}
virtual void log(Statement &statement) = 0;
};
Statement::~Statement() {
logger->log(*this);
}
//------------------------------------------------------------------------------
struct MyLogger : public Logger {
virtual void log(Statement &statement) override {
for (auto &&component : statement) {
std::cout << component.toString();
}
std::cout << std::endl;
}
};
int main() {
std::string variable = "string";
MyLogger logger;
//logger << wrap("Option ") << wrap(variable) << wrap(" is ") << wrap(42);
logger << 42;
logger << variable << " is " << 42;
logger << "Option " << variable << " is " << 42;
}
this will print:
42
string is 42
Option string is 42
UPD
as dyp advised here is alternative implementation of the Component structure without lambda:
struct Component
{
mutable Component *next;
void* value;
std::string toString(){
return _toString(this);
}
template<typename T>
Component(const T& inValue)
: next(nullptr),
value((void*)&inValue),
_toString(toStringHelper<T>)
{}
private:
typedef std::string(*ToStringFunction)(Component*);
ToStringFunction _toString;
template<typename T>
static std::string toStringHelper(Component* component)
{
const T& value = *(T*)component->value;
std::stringstream ss;
ss << value;
return ss.str();
}
};
I propose a solution tuple based:
template <class... Ts> class streamTuple;
struct Logger {
template <typename T>
streamTuple<T> operator<<(const T& t);
template <typename Tuple, std::size_t ... Is>
void dispatch(const Tuple& tup, std::index_sequence<Is...>)
{
int dummy[] = {0, (void(std::cout << std::get<Is>(tup) << " "), 0)...};
static_cast<void>(dummy); // Avoid unused variable warning
}
// Logger can take generic functor to have specific dispatch
// Or you may reuse your virtual method taking ComponentBase.
};
template <class... Ts> class streamTuple
{
public:
streamTuple(Logger* logger, const std::tuple<Ts...>& tup) :
logger(logger), tup(tup) {}
streamTuple(streamTuple&& rhs) : logger(rhs.logger), tup(std::move(rhs.tup))
{
rhs.logger = nullptr;
}
~streamTuple()
{
if (logger) {
logger->dispatch(tup, std::index_sequence_for<Ts...>());
}
}
template <typename T>
streamTuple<Ts..., const T&> operator << (const T& t) &&
{
auto* moveddLogger = logger;
logger = nullptr;
return {moveddLogger, std::tuple_cat(tup, std::tie(t))};
}
private:
Logger* logger;
std::tuple<Ts...> tup;
};
template <typename T>
streamTuple<T> Logger::operator<<(const T& t) {
return {this, t};
}
Demo
And usage:
int main() {
Logger log;
std::string variable = "string";
log << variable << 42 << "hello\n";
}
I have an "object" with different attributes stored as key/value. The key is a string and the value can be any basic type. My first idea was using a template class:
template <class T>
class Attribute {
public:
Attribute<T>(const std::string& key, T value) :
m_key(key),
m_value(value)
{
}
~Attribute(){}
T getValue() const
{
return m_value;
}
std::string getKey() const
{
return m_key;
}
private:
std::string m_key;
T m_value;
};
But now the problem is that in my object class, I have to declare fields and overload functions for each possible attribute type:
class MyObject {
public:
MyObject(int value) :
m_value(value)
{
}
~MyObject()
{
}
int getValue() const
{
return m_value;
}
void addAttribute(Attribute<int> attribute)
{
m_intAttributes.push_back(attribute);
}
void addAttribute(Attribute<double> attribute)
{
m_doubleAttributes.push_back(attribute);
}
const std::list<Attribute<int> >& getIntAttributes() const
{
return m_intAttributes;
}
const std::list<Attribute<double> >& getDoubleAttributes() const
{
return m_doubleAttributes;
}
private:
int m_value;
std::list<Attribute<int> > m_intAttributes;
std::list<Attribute<double> > m_doubleAttributes;
};
Moreover, iterating through the attributes is not very comfortable and looking for an attribute of a given name is very difficult:
void showMyObject(const MyObject& myObject)
{
std::list<Attribute<int> > intAttributes;
std::list<Attribute<int> >::const_iterator itInt;
std::list<Attribute<double> > doubleAttributes;
std::list<Attribute<double> >::const_iterator itDouble;
std::cout << "Value in myObject " << myObject.getValue() << std::endl;
intAttributes = myObject.getIntAttributes();
for(itInt = intAttributes.begin() ; itInt != intAttributes.end() ; itInt++)
{
std::cout << itInt->getKey() << " = " << itInt->getValue() << std::endl;
}
doubleAttributes = myObject.getDoubleAttributes();
for(itDouble = doubleAttributes.begin() ; itDouble != doubleAttributes.end() ; itDouble++)
{
std::cout << itDouble->getKey() << " = " << itDouble->getValue() << std::endl;
}
}
FYI, my main function looks like this:
int main(int argc, char* argv[])
{
MyObject object(123);
object.addAttribute(Attribute<double>("testDouble", 3.23));
object.addAttribute(Attribute<double>("testDouble2", 99.654));
object.addAttribute(Attribute<int>("testInt", 3));
object.addAttribute(Attribute<int>("testInt2", 99));
showMyObject(object);
return 0;
}
I guess if we want to guarantee type safety, there must be somewhere list of functions with the right return type in the signature (getTYPEAttributes in my example).
However, I was wondering if a more elegant solution exists and if a design pattern I'm not aware of could help me to handle this problem correctly.
Sounds like a job for Boost.TypeErasure. You want to store different kinds of things that share common traits (are streamable, have a key), but can be explicitly accessed and don't need a common base? Store your attributes thusly:
namespace mpl = boost::mpl
using namespace boost::type_erasure;
BOOST_TYPE_ERASURE_MEMBER((has_getKey), getKey, 0)
using AnyAttribute = any<mpl::vector<
copy_constructible<>,
typeid_<>,
ostreamable<>, // add a stream operator for Attribute
has_getKey<std::string(), const _self>
> >;
std::vector<AnyAttribute> attributes;
Adding an attribute would look like:
template <typename T>
void addAttribute(const std::string& key, const T& value) {
// since Attribute<T> is copy-constructible, streamable,
// and has a member function with the signature std::string getKey() const
// we can construct an AnyAttribute with it.
attributes.push_back(Attribute<T>(key, value));
}
Printing all of the attributes:
void showMe() {
for (const auto& attr : attributes) {
std::cout << attr << ' '; // since we specified ostreamable<>,
// everything we put into this any<> is streamable
// so the any<> is too
}
std::cout << '\n';
}
Looking up an attribute by name and specified type, returns nullptr if not found or wrong type:
template <typename T>
const Attribute<T>* lookupAttribute(const std::string& key) {
// can use getKey() even if they're all different types
// because we added has_getKey<> as a concept
auto it = std::find_if(attributes.begin(), attributes.end(),
[=](const AnyAttribute& a) {
return a.getKey() == key;
});
if (it != attributes.end()) {
// this will return a valid Attribute<T>* you specified the
// correct type, nullptr if you specified the incorrect type
// it is not possible to query the type.
return any_cast<Attribute<T>*>(&*it);
}
else {
return nullptr;
}
}
There's a simpler type-erased object which is just Boost.Any, but there you cannot have any kind of common functionality - which would make it difficult to implement either the lookup or the printing operations I illustrated above.