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>());
Related
I have question about having a std::function object as a data member for my class. I would like for it to accept two types of functions, either with one or two parameters of the same kind. Is there some strategy for doing this, perhaps involving template meta programming?
Here's a copy of my code so far, and to be clear I would like it to only accept std::function<matrix (matrix, matrix)> and std::function<matrix (matrix)> .
struct RegisteredOPS {
using matrix = std::shared_ptr<Matrix::Representation>;
enum Type { NOP, MM, PLUS, ReLU,};
Type m_type;
std::function<matrix (matrix, matrix)> m_func;
RegisteredOPS(Type _typ, std::function<matrix
(matrix, matrix)> _fun): m_type(_typ), m_func(_fun) {}
};
As a followup, I went and followed the suggestion of
#Lala5th, my question is if there is any way to wrap a functor object in std::function<matrix (matrix, matrix)> ?
I have the following Base class Functor adhering to CRTP:
template <class Implementation>
class BaseOp {
public:
virtual std::unique_ptr<Matrix::Representation> operator()(
std::unique_ptr<Matrix::Representation>& l,
std::unique_ptr<Matrix::Representation>& r) {
return Impl().operator()(l, r);
}
virtual ~BaseOp() = default;
private:
BaseOp& Impl() { return *static_cast<Implementation*>(this); }
BaseOp() = default;
friend Implementation;
};
where I am attempting to pass it via this function:
void RegisterOperator::visit(std::unique_ptr<MatrixMultiplyStep> mm) {
std::string context_object_data = "Matrix_multiply";
auto operand = mm->giveOperand();
RegisteredOperation op = RegisteredOperation(
RegisteredOperation::MM,
&Matrix::Operations::
Multiplication::ParallelDNC::operator(),
std::make_pair(std::move(this->prev_operand), std::move(operand)));
this->computational_graph.emplace_back(op);
// mm->forward(std::make_unique<this>());
}
However I ended up with this error.
tensor.cpp:20:42: error: no matching constructor for initialization of 'NeuralNetwork::Computation::Graph::RegisteredOperation'
RegisteredOperation op = RegisteredOperation(
^
include/tensor.h:59:21: note: candidate constructor not viable: no known conversion from 'std::unique_ptr<Matrix::Representation> (Matrix::Operations::Multiplication::ParallelDNC::*)(std::unique_ptr<Matrix::Representation> &, std::unique_ptr<Matrix::Representation> &)' to 'NeuralNetwork::Computation::Graph::RegisteredOperation::Function' (aka 'variant<function<unique_ptr<Matrix::Representation> (unique_ptr<Matrix::Representation>, unique_ptr<Matrix::Representation>)>, function<unique_ptr<Matrix::Representation> (unique_ptr<Matrix::Representation>)>, function<void ()>>') for 3rd argument
RegisteredOperation(Type _typ, std::string _dat, Function _fun, Operands _op):
Thank you!
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).
Okay, the title is a mouthful and hopefully specific enough, but I'm running into a C++ issue which I think is possible, I just can't seem to find the proper syntax.
I have a simple template-based property class:
template <typename T>
class Property
{
public:
Property<T> &operator = (const T &src)
{
m_data = src;
return *this;
};
operator const T& () const
{
return m_data;
}
private:
T m_data;
};
I need to assign values from a QVariant, which is also sort of a property but without templates. At the moment I am deferencering the values explicitly when assigning:
Property<QString> p1;
Property<int> p2;
p1 = var1.toString();
p2 = var2.toInt();
This works but it is tedious and I'm sure the compiler can do the work for me. So, I tried implementing specialized assignment operators based on the typename of the Property; in other words, if the template specialization is based on a QString use one function, if it is based on an int use another function, et cetera.
I tried things like:
Property<QString> &operator = (const QVariant &ref)
{
m_data = ref.toString ();
return *this;
};
or...
template <typename int> &Property<int>::operator = (const QVariant &ref)
{
m_data = ref.toInt ();
return *this;
};
or...
template<> Property<T> &Property<QString>::operator = (const QVariant &ref)
{
m_data = ref.toString ();
return *this;
}
..both inside and outside of the class declaration but to no avail. I get errors like "expected nested-name-specifiers", "two or more data types in declaration of parameters" and the like.
Any pointers to the correct syntax would be appreciated!
PS: the first declaration compiles witout error, but adding the same declaration for <int> makes it ambiguous since only the return type differs.
Compiler is GCC 4.8.2 with --stdc=c++11 enabled.
Although the answer of paddy seems correct, it seems to me tedious to generalize it (implement a specialzed assignment operator to all the types that a QVariant can hold, in addition to QString and int).
An easier solution would be to specialize the assignment operator once for all, in a way that benefits from the built-in conversions that the QVariant provides:
Property& operator= (const QVariant& src)
{
assert(src.canConvert<T>());
m_data = src.value<T>();
return *this;
}
The original class definition is a bit wrong, as pointed out by Kirill Kobelev in your question's comments section. Now, let's fix that and also add another operator=:
template <typename T>
class Property
{
public:
Property & operator=( const T & src )
{
m_data = src;
return *this;
}
// This one must be specialized
Property & operator=( const QVariant & src );
const T & operator() const
{
return m_data;
}
private:
T m_data;
};
The specialization is therefore quite simple. Here's ones for QString and int:
template <>
Property<QString> &
Property<QString>::operator=( const QVariant & src )
{
return operator=( src.toString() );
}
template <>
Property<int> &
Property<int>::operator=( const QVariant & src )
{
return operator=( src.toInt() );
}
Now you are free to assign QVariant values directly to any Property which provides that specialization. If you try to do it on a class that did not specialize then you will get an error.
I don't have the reputation to comment, nor the expertise to claim insight so please don't take this as an "answer".
But your question reminded me of a lesson on Cpp, Overloads and Functions over at http://www.cplusplus.com/doc/tutorial/functions2/ .
Excerpt:
"In the example above, we used the function template sum twice. The first time with arguments of type int, and the second one with arguments of type double. The compiler has instantiated and then called each time the appropriate version of the function.
Therefore, result will be a variable of the same type as the parameters a and b, and as the type returned by the function.
In this specific case where the generic type T is used as a parameter for sum, the compiler is even able to deduce the data type automatically without having to explicitly specify it within angle brackets."
Apologies if I missed the point, but thought this may help.
How do I make a class in C++, when initialized, return a Boolean value when its name is invoked, but no explicit function call make, like ifstream. I want to be able to do this:
objdef anobj();
if(anobj){
//initialize check is true
}else{
//cannot use object right now
}
not just for initialization, but a check for its ability to be used.
The way istream does it is by providing an implicit conversion to void*
http://www.cplusplus.com/reference/iostream/ios/operator_voidpt/
stream output and implicit void* cast operator function invocation
Update In reaction to the comments, the Safe Bool Idiom would be a far better solution to this: (code directly taken from that page)
class Testable {
bool ok_;
typedef void (Testable::*bool_type)() const;
void this_type_does_not_support_comparisons() const {}
public:
explicit Testable(bool b=true):ok_(b) {}
operator bool_type() const {
return ok_==true ?
&Testable::this_type_does_not_support_comparisons : 0;
}
};
template <typename T>
bool operator!=(const Testable& lhs,const T& rhs) {
lhs.this_type_does_not_support_comparisons();
return false;
}
template <typename T>
bool operator==(const Testable& lhs,const T& rhs) {
lhs.this_type_does_not_support_comparisons();
return false;
}
The article by Bjorn Karlsson contains a reusable implementation for the Safe Bool Idiom
Old sample:
For enjoyment, I still show the straight forward implementation with operator void* overloading, for clarity and also to show the problem with that:
#include <iostream>
struct myclass
{
bool m_isOk;
myclass() : m_isOk(true) { }
operator void* () const { return (void*) (m_isOk? 0x1 : 0x0); }
};
myclass instance;
int main()
{
if (instance)
std::cout << "Ok" << std::endl;
// the trouble with this:
delete instance; // no compile error !
return 0;
}
This is best accomplished using the safe bool idiom.
You provide an implicit conversion to a member-function-pointer, which allows instances of the type to be used in conditions but not implicitly convertyed to bool.
You need a (default) constructor and an operator bool()().
class X {
public:
operator bool ()const{
//... return a boolean expression
}
};
usage:
X x; // note: no brackets!
if( x ) {
....
}
You'll want to create an operator bool function (or as boost does, an unspecified_bool_type that has certain improved properties I can't recall offhand). You may also want to create operator! (For some reason I seem to recall iostreams do this too).
I'm making some stack, in which I need to uses this kind of comparison in some function. But I got stuck since I don't know how the prototype for this should look like.
I have the following line in a function.
template <class T>
void function1(T i)
{
if(i == 'a')
//do something
}
I wonder know how the overload prototype should look like for it?
EDIT
Dunno if it's worth to mention, anyway this is what I have tried so far
template
bool Stack<T>::operator==(char c) const
{
cout << c << endl; // just some test
}
No need to comment how this function works, as I have not finished it yet. This part will compile, however at the part where I call this function for the first time is in the Stack::push(T i). The compiler will complain that there are no matching function for this.
error: no match for 'operator==' in 'i == '#''
For overloading operators, the name of the function is operator followed by the actual operator, so operator==. It returns bool. I don't know what your arguments should be based on your code. Probably Stack<T>&, and you need two of them to compare if it's a free function, and one to compare to this if it's a member function.
If you have ways to convert to a Stack<T>, then prefer a free function so that you can convert the left-hand-side.
I'm not sure I understand your question. In order for an instantiation of template function function1 to be well-formed, you'll have to provide a operator== which compares a T and (I'll suppose) a char.
Now, you have two options here :
Provide a bool operator==(char) const member function in your type, for example :
struct A {
bool operator==(char) const { /* ... */ }
};
function1(A()); // OK : comparison uses A::operator==(char)
Provide bool operator==(const T &, char) as a free function, for example :
struct A { /* ... */ };
bool operator==(const A &, char) { /* ... */ }
function1(A()); // OK : comparison uses operator==(const A &, char)
So every T in your function1(t) has to implement operator ==;
For example, as a member function
class A
{
public:
bool operator == (char) const;
};
or a non-member operator:
class A
{
public:
friend bool operator == (const A&, char);
};