I have a Exception base class which defines a stream function:
class Exception
{
public:
template <typename TData, typename TException>
TException& stream(const TData& data)
{
stream_ << data;
return *reinterpret_cast<TException*>(this);
}
};
I have a free function overloading operator<<:
template <typename TData>
Exception& operator<<(Exception& ex, const TData& data) {
return ex.stream<TData, Exception>(data);
}
I also have dervied exceptions overloading operator<<:
template <typename TData>
CoffeeException& operator<<(CoffeeException& ex, const TData& data) {
return ex.stream<TData, CoffeeException>(data);
}
I use this like so:
else {
throw CoffeeException() << "Exception text";
}
When I try to use the class the compiler doesn't see the function, it just suggests the standard stream operators avaiable but doesn't note my Exception or CoffeeException free functions. Does this implementation look correct?
It looks like the usual problem of trying to bind a temporary to a
non-const reference. CoffeeException() << "Exception text" can't bind
to your operator<<, because CoffeeException() is a temporary. Just
make your operator<< a member:
class CoffeeException : public Exception
{
// ...
public:
template <typename TData>
CoffeeException& operator<<( TData const& data )
{
stream( data );
return *this;
}
};
While I'm at it: you definitely don't want the reinterpret_cast at the
end of Exception::stream. Using the results of this cast is undefined
behavior. It will typically work in cases of single inheritance, but
fail where multiple inheritance is involved (but even that isn't
guaranteed). The simplest solution is what I've done above (and make
Exception::stream return void); alternatively, use static_cast
here (which should be legal if the inheritance is defined at the point
of instantiation).
CoffeeException& operator<<(const CoffeeException& ex, const TData& data);
This reference must be const, because you try pass unnamed object.
You can also create temporary object to avoid using const reference.
Related
I have a class like this:
class factory;
using factory_ptr = std::unique_ptr<IComponent> (factory::*)() const noexcept;
class factory {
public:
factory();
~factory() = default;
std::unique_ptr<Chipset> &create(const std::string &type);
private:
template<class T>
std::unique_ptr<T> Tcreate() const noexcept;
std::map<std::string, factory_ptr> m_fac;
};
#include "factory.inl"
My template function Tcreate is just:
template<class T>
std::unique_ptr<T> factory::Tcreate() const noexcept {
return std::make_unique<T>();
}
And the other function are just:
factory::factory() {
m_fac.emplace("4001", &factory::Tcreate<chipset4001>);
m_fac.emplace("4008", &factory::Tcreate<chipset4008>);
m_fac.emplace("4011", &factory::Tcreate<chipset4011>);
m_fac.emplace("4030", &factory::Tcreate<chipset4030>);
m_fac.emplace("4069", &factory::Tcreate<chipset4069>);
m_fac.emplace("4071", &factory::Tcreate<chipset4071>);
m_fac.emplace("4081", &factory::Tcreate<chipset4081>);
m_fac.emplace("4512", &factory::Tcreate<chipset4512>);
}
std::unique_ptr<Chipset> &factory::create(const std::string &type) {
if (m_fac.find(type) == m_fac.end()) {
throw nts::exception("can't find the chipset: " + type, "FactoryCreate");
}
return (this->*(m_fac.find(type)->second))();
}
Every chipset like chipsetXXXX are a class like:
class chipsetXXXX : Chipset {}
What I want to do here with this code is to generate an std::unique_ptr<> of a certain chipset linked with a string (cf. factory::m_fac), but when I run it a lot of error message pop on my terminal (more than what my terminal can handle). but i can't figured out what go wrong with it.
The issue is that your Tcreate function does not have the required signature. You're trying to create a map of functions which return an std::unique_ptr<IComponent>, but Tcreate() returns std::unique_ptr<T>.
I'm assuming Chipset inherits from IComponent. And as you note each T inherits from Chipset. So the conversion from e.g. std::unique_ptr<chipset4001> to std::unique_ptr<IComponent> is certainly possible, but that doesn't mean that the signature matches. E.g. a pointer to a function double do_thing () can't be assigned to a function pointer expecting an int (*) ().
So the solution is to change the return type of Tcreate to std::unique_ptr<IComponent>:
template<class T>
std::unique_ptr<IComponent> factory::Tcreate() const noexcept {
return std::make_unique<T>();
}
However, when you do that, you'll now get a compile error in create(), because that tries to return an std::unique_ptr<Chipset>. It's up to you to decide what to do there. Either return std::unique_ptr<IComponent>, or change factory_ptr to be a pointer to a function returning std::unique_ptr<Chipset> (and of course change Tcreate() accordingly).
template <typename T>
class Obj {
public:
Obj<T>* doThis();
const Obj<T>* doThis() const {// return normal version of doThis()}
};
In the example, I want the const version of doThis() to return normal version of doThis(). I don't think it's ok to just put return doThis() in definition of const version of doThis() because C++ may think this is recursion of const version of doThis().
Is there any way to explicitly tell C++ which function to call?
As Story Teller mentioned in the comment, don't do this, because this can lead to UB, e.g., in this simple case:
const Obj<int> obj;
obj.doThis(); // UB since you will have to const_cast<Obj<int>&>(obj).
The proper thing is to do it the other way:
template <typename T>
class Obj {
public:
Obj<T>* doThis() {
return const_cast<Obj<T>*>(std::as_const(*this).doThis());
}
const Obj<T>* doThis() const { /* Actual implementation. */ }
};
Note that this implies that the return value of doThis() const can be safely const_cast back to Obj<T>* (e.g., if you return this in doThis, this is safe).
If you cannot implement doThis() in the const-qualified version, then your code is probably flawed.
VisualStudio 2008 (VC++ 9)
Problem with overloading operator()
Hello community!
It seems that overloaded version of operator() must all differ in their argument list, independly of the return type.
I have the following case:
class Sha256{
public:
QVector<quint32> operator()(QString const& data);
QByteArray operator()(QByteArray const& data);
QVector<quint32> operator()(QByteArray const& data); // this is line 168
...
}
Last declaration leads to following compilation error:
.\sha256.cpp(168) : error C2556: 'QVector Sha256::operator ()(const QByteArray &)' : overloaded function differs only by return type from 'QByteArray Sha256::operator ()(const QByteArray &)'
with
[
T=uint
]
On the other side, following declarations are working:
class Sha256{
public:
QVector<quint32> operator()(QString const& data);
QByteArray operator()(QByteArray const& data);
...
}
because they have different arguments.
One way would be to add in the first case an additional argument like
QByteArray<quint32> operator()(QByteArray const& data, bool getByteArray)
but this is embarassing, not intuitive and also not clean (return type would be a QByteArray, independly of the value of getByteArray, even in case of false!).
Another way could be to use a template function like
template<class T> T operator()(QByteArray const& ba)
template<class T> T operator()(QString const& str)
but T could only be of a few 'supported' type (QByteArray and QVector), therefore user could run into trouble if using wrong T Type. This version seems to be error prone.
So my questions are:
1. Why is the return type of function objects not taken into account in the signature to distinguish between different flavors of the function like in 'classical' functions?
2. Is there a better way around than adding an additional dummy argument?
Thank you for your valuable time.
Alain
Return type is never used for overload resolution. In fact, you can't even declare two functions that differ only in return type. In my opinion, adding this feature would be complicated and not that helpful. Is it necessary to use the function call operator? You could just use a named member function, and then give them different names. Another option would be to use a member template, but even then you would need to explicitly give the return type as a template argument, and the syntax would be ugly if done on the function call operator.
The comment from Kerrek SB suggests a workaround by leveraging conversion operators, if you are okay with something that is complex on the inside, but simpler on the outside.
#include <iostream>
struct A {};
struct B {};
A fooA_impl(const char *) {
std::cerr << "A impl" << std::endl;
return A();
}
B fooB_impl(const char *) {
std::cerr << "B impl" << std::endl;
return B();
}
class Helper {
public:
operator A() { return fooA_impl(p); }
operator B() { return fooB_impl(p); }
private:
friend Helper foo(const char *p);
Helper(const char *p_) : p(p_) {}
const char *const p;
};
Helper foo(const char *p) {
return Helper(p);
}
int
main() {
A a(foo("hello"));
B b(foo("hello"));
}
You can't use overload by return type. One thing you can do is to add the return type as a tag parameter when overloading operator():
QByteArray operator()(QByteArray const& data, const QByteArray& tag );
QVector<quint32> operator()(QByteArray const& data, const QVector<quint32>& tag);
The below is how you call these function:(assume both types have default constructors).
(data, QByteArray());
(data, QVector<quint32>());
In C++03, when you were to wrap a bunch of C functions in a class to create an 'auto object', you had to customize the object to the type of functions it encapsulated. As an example, to wrap a windows file HANDLE, you needed to call CloseHandle() in the destructor and CreateFile() in the constructor. The constructor would need to mimic the function signature of the CreateFile() function, sans the file HANDLE variable (since it's being managed).
Anyway, what I'd like to know is if it's possible to use the new features of C++11 to create a single generic class that can be used to wrap any type of resource by only providing an implementation for creation and deletion?
One problem I foresee is that the creation function, such as noted above with CreateFile(), can taken any number of parameters. Is there a way to auto-magically generate a templated constructor that mimics the signature of the function? Variadic Parameters come to mind, but I have not yet used them.
Has anyone tried writing something like this?
EDIT: Some code to help illustrate (pseudo):
template<typename Res, FunctionPtrToCreatorFunc Func, typename... Arguments>
class creator
{
public:
operator()(Res &r, Arguments... Args)
{
Func(r, /*use args?*/ Args); // Allocate resource, ie. CreateFile(r, args)
}
};
template<typename Res, FunctionPtrToDeleterFunc Func>
class deleter
{
operator()(Res &r)
{
Func(r); // delete the resource, ie. CloseHandle(r)
}
};
Then this will be the implementation of my super auto object:
template<typename Res, typename Creator, typename Deleter>
class auto_obj
{
public:
auto_obj(/*somehow copy Args from Creator class?*/)
{
Creator(_res, /*args?*/);
}
~auto_obj()
{
deleter(_res);
}
Res _res;
};
Yes, this has a similar structure to shared_ptr or unique_ptr, but instead the constructor will be the one that creates the resources by developer written creator and deleter classes. I have a feeling that std::bind may play a role in this, but I have never used it.
Here is a stab at it:
#include <utility>
#include <type_traits>
#include <cstddef>
A more friendly way to wrap up a function. I move the signature boilerplate to this template, instead of messing up the actual RAII class below. This also allows full fledged function objects to be used, as well as functions, in the RAII class below:
template< typename FuncSig, FuncSig func >
struct Functor {
template<typename... Args>
auto operator()(Args&&... args) const
-> decltype( func(std::forward<Args>(args)...) )
{ return ( func(std::forward<Args>(args)...) ); }
};
One operation that is needed for more than basic functionality is the ability to "null" a handle, allowing invalid handles to exist, and allowing handles to be moved around. Zeroer is my default function object for "null"ing a handle:
struct Zeroer {
template<typename T>
void operator()( T& t ) const {
t = 0;
}
};
RAII_handle herself. You pack the creation and destruction signatures into it, and it forwards construction to the underlying data. .close() lets you close the RAII_handle early, which is a common requirement in practice. You access the underlying data via operator* or operator->, and while this makes it look pointer-like, RAII_handle does not obey pointer semantics. It is a move-only type.
template< typename T, typename Creator, typename Destroyer, typename Nuller=Zeroer >
struct RAII_handle {
RAII_handle( std::nullptr_t ):
data()
{
Nuller()(data);
}
RAII_handle( RAII_handle const& ) = delete;
RAII_handle( RAII_handle && o ):data(std::move(o.data)) {
Nuller()(o.data);
}
RAII_handle& operator=( RAII_handle const& ) = delete;
RAII_handle& operator=( RAII_handle && o ) {
data = std::move(o.data);
Nuller()(o.data);
return *this;
}
template<typename... Args>
RAII_handle( Args&&... args ):
data( Creator()(std::forward<Args>(args)...) )
{}
auto close()->decltype( Destroyer()(std::declval<T&>()) ) {
auto retval = Destroyer()(data);
Nuller()(data);
return retval;
}
~RAII_handle() {
close();
}
T& get() { return data; }
T const& get() const { return data; }
T& operator*() { return get(); }
T const& operator*() const { return get(); }
T* operator->() { return &get(); }
T const* operator->() const { return &get(); }
private:
T data;
};
Now, some test code. My file handles will be unsigned char, and opening/closing will simply test if things are not working right.
#include <iostream>
typedef unsigned char HANDLE;
HANDLE CreateFile( char const* name ) {
std::cout << name << "\n";
return 7;
}
bool CloseFile( HANDLE h ) {
if (h) {
--h;
std::cout << (int)h << "\n";
return true;
} else {
std::cout << "already closed\n";
return true;
}
}
Once you have your open/close functions or function objects, here is how you make the type of the FileHandle:
typedef RAII_handle< HANDLE, Functor< HANDLE(*)( char const* ), CreateFile >, Functor< bool(*)(HANDLE), CloseFile > > FileHandle;
You can support entire overload sets by simply creating a function object that forwards to a fixed function name, instead of to a fixed function pointer. Basically take Functor above, remove the template signature and pointer, and replace the use of func with actual use of your function name.
Suddenly your function object represents not calling one function, but calling an entire overload set.
Fancier work can even support multiple functions, allowing one function object to support calling either CreateFile or CreateFileEx depending on what arguments are passed in.
And here is our trivial test code:
int main() {
FileHandle bob("hello.txt");
HANDLE value = *bob; // get the HANDLE out of the FileHandle
bob.close(); // optional, to close early
}
Requirements: your CloseFile must accept Nuller()(std::declval<T&>()) and not behave badly. The default Nuller()(...) just assigns zero to your T, which works for many handle types.
It supports move semantics, allowing you to return these from a function, but I didn't include a Copier argument (which I'd expect would be required for any RAII objects that can be copied).
Live example with very slightly different code.
Let me say we have a simple programming task. But for the sake of clarity I start with few code samples.
First of all we written a some kind of data container class but for the purposes of task no matter what the class is. We just need it to behave const-correct.
class DataComponent {
public:
const std::string& getCaption() const {
return caption;
}
void setCaption(const std::string& s) {
caption = s;
}
private:
std::string caption;
};
Then let us assume we've got a generic class that behaves like facade over arbitrary incapsulated class instance. Say we overloaded member access operator (->).
template <typename T> class Component {
public:
Component() { instance = new T(); }
...
const T* operator-> () const {
return instance;
}
T* operator-> () {
// but there might be additional magic
return instance;
}
private:
T *instance;
};
At this point I should say how I want this to work:
if we're calling non-const member functions of underlying class through member access operator (component->setCaption("foo")) compilier treats non-const T* operator-> () as the best choice.
otherwise if we are trying to call const member functions of underlying class same way (component->getCaption()) compiliers selects const T* operator-> () const on the other hand.
This code sample above won't work this way so I'm curious about possibility to give compiler a behavior like that I have mentioned. Any propositions.
EDIT: Let our member access operator overloaded this way:
const T* operator-> () const { return instance; }
T* operator-> () {
cout << "something going change" << endl;
return instance;
}
And let us have a variable Component<DataComponent> c somewhere. Then on the call to c->getCaption() stdout should remain silent but on the call to c->setCaption("foo") stdout should warn us that something is going to change. VS 2010 compilier makes stdout warn us on each of these calls.
I understand that such semantics suppose that c behaves as const and non-const at the same time. But curiousity is still in my mind.
Whether a const or non-const member is invoked is determined purely by the constness of the object on which it is invoked, not by some subsequent operation. That determination is made before any consideration of the particular method you're invoking in DataComponent. You could still hack up the required functionality less directly using proxy object around DataComponent, with both const and non-const forwarding getCaption()s.
EDIT: details as requested (off the top of my head). You'll need to forward declare some of this stuff - I didn't bother as it makes it even more confusing. Do chip in with any concerns / feedback. Note that this basically assumes you can't / don't want to modify Component for some reason, but it's not a generic templated solution that can simply be wrapped around any arbitrary type - it's very heavily coupled and has a high maintenance burden.
// know they can't call a non-const operation on T, so this is ok...
const T* Component::operator->() const { return instance; }
// they might invoke a non-const operation on T, so...
DataComponent::Proxy Component::operator->() { return DataComponent.getProxy(*this); }
in class DataComponent:
struct Proxy
{
Component& c_;
DataComponent& d_;
Proxy(Component& c, DataComponent& d) : c_(c), d_(d) { }
const std::string& get_caption() const { return d_.get_caption(); }
void set_caption(const std::string& s)
{
c_.on_pre_mutator(d_);
d_.set_caption(s);
c_.on_post_mutator(d_);
}
};
then
DataComponent::Proxy DataComponent::getProxy(Component& c) { return Proxy(c, *this); }
So, this means somewhere you have to hand-code forwarding functions. It's a pain, but if you're doing this for debugging or testing it's not unreasonable. If you're doing this so you can add a lock or something, then there are probably better alternatives.