I'm trying to override the << operator but it seems that the compiler doesn't recognize my implementation and instead tries to interpret it as a bit shift.
I've already tried to play around with the parameter types (const T&, T&, T, const T) to no avail.
#pragma once
template<typename T> class AbstractStack
{
public:
virtual bool Push(const T &) = 0;
}
template <typename T> class ArrayStack : public AbstractStack <T>
{
public:
bool Push(const T&) {
....
}
}
template <typename T> bool operator<<(const AbstractStack<T>* &, const T&) {
return stack->Push(item);
}
int main() {
AbstractStack<int> *stack = new ArrayStack<int>(5);
int a = 2;
stack << a; // <<-- compiler error
return 0;
}
The error reported is:
Error (active) expression must have integral or unscoped enum type Lab10
Error C2296 '<<': illegal, left operand has type 'AbstractStack<int> *'
If I define the same operator acting on the class as a value, it just works...
When overloading operators, at least one of the arguments must be a class or an enum type - basically this allows/limits you to overloading custom types (user defined types).
From the cppreference;
When an operator appears in an expression, and at least one of its operands has a class type or an enumeration type, then overload resolution is used to determine the user-defined function to be called among all the functions whose signatures match the following...
This makes sense in that it disallows you from overloading the built in types; in this case, the pointer and integer you have as arguments.
As you already remarked in the question, the solution is taking your first argument by reference;
template <typename T>
bool operator<<(AbstractStack<T> &, const T&)
{ //...
Given the abstract base class you are looking to use, you could investigate the use of std::shared_ptr to help manage the resources and make the use of a "pointer" in the overloaded operator (albeit it will be a smart pointer);
template <typename T>
bool operator<<(std::shared_ptr<AbstractStack<T>>&, const T&)
{
return stack->Push(item);
}
int main() {
std::shared_ptr<AbstractStack<int>> stack = std::make_shared<ArrayStack<int>>(5);
int a = 2;
stack << a;
return 0;
}
As others have said, overloading any builtin operator requires an object of a user-defined type; a pointer won't work. And the solution is to use an object instead of a pointer:
template <typename T> bool operator<<(AbstractStack<T>&, const T&) {
return stack.Push(item);
}
and then call it with an object. There's no good reason in the code you've shown to allocate from the free-store; just create an auto object:
int main() {
ArrayStack<int> stack(5);
int a = 2;
stack << a;
return 0;
}
Related
I want to refer to function pointers of built-in operators, but I don't know how to specify the specific type overloads.
I have the following template class signature:
template<typename ParamsType, typename FnCompareType>
class MyAction
{
public:
MyAction(ParamsType& arg0, ParamsType& arg1, FnCompareType& fnCpmpare)
: arg0_(arg0), arg1_(arg1), fnCompare_(fnCpmpare) {}
bool operator()()
{
if((*fnCompare_)(arg0_,arg1_)
{
// do this
}
else
{
// do s.th. else
}
}
private:
ParamsType& arg0_;
ParamsType& arg1_;
FnCompareType& fnCompare_;
}
And want to use a syntax like this:
void doConditional(int param1, int param2)
{
MyAction<int,&::operator>=> action(param1,param2);
if(action())
{
// Do this
}
else
{
// Do that
}
}
But that doesn't compile:
error: ‘::operator>=’ has not been declared
What can I do to refer to such intrinsic static operations?
Built-in operators
Why you cannot have function pointers of them:
C++11, §13.6/1, [over.built]
The candidate operator functions that represent the built-in operators defined in Clause 5 are specified in this subclause. These candidate functions participate in the operator overload resolution process as described in 13.3.1.2 and are used for no other purpose.
Built-in operators (those for the built-in types) aren't real operator functions. So you can't have function pointer pointing to them. You also cannot invoke them using operator<(A,B) syntax.
They only participate in overload resolution but the compiler will translate them directly into the appropriate asm/machine instruction without any kind of "function call".
The way to get around this issue:
user1034749 has already answered this question, but for completeness:
The standard defines a lot of function objects in §20.8, [function.objects], i.e.
Arithmetic operations
Comparisons
Logic operations
Bitwise operations
A function object is an object of a function object type. In the places where one would expect to pass a pointer to a function to an algorithmic template (Clause 25), the interface is specified to accept a function object. This not only makes algorithmic templates work with pointers to functions, but also enables them to work with arbitrary function objects.
C++11, §20.8.5, [comparisons]
equal_to
not_equal_to
greater, less
greater_equal
less_equal
Those are templated function objects which decay to the analogous operator in their operator() function. They can be used as function pointer arguments.
user1034749 is right, I want to state: There's no other way, these are completely equivalent in usage to 'raw' function pointers. Reference given.
Standard class type operators
You can use standard library operators as function pointers (which are present as "real functions").
But you'll have to refer to the respective instance of the template. The compiler will need appropriate hints to deduce the correct template.
This works for me on MSVC 2012 using operator+ of std::basic_string
template<class Test>
Test test_function (Test const &a, Test const &b, Test (*FPtr)(Test const &, Test const &))
{
return FPtr(a, b);
}
int main(int argc, char* argv[])
{
typedef std::char_traits<char> traits_t;
typedef std::allocator<char> alloc_t;
std::basic_string<char, traits_t, alloc_t> a("test"), b("test2");
std::cout << test_function<std::basic_string<char, traits_t, alloc_t>>(a, b, &std::operator+) << std::endl;
return 0;
}
If the template argument of test_function is left out to be deduced this will fail (at least for MSVC 2012).
You can use the same solution as used in C++ standard library:
std::sort (numbers, numbers+5, std::greater<int>());
where greater is
template <class T> struct greater : binary_function <T,T,bool> {
bool operator() (const T& x, const T& y) const {return x>y;}
};
in your case http://www.cplusplus.com/reference/functional/greater_equal/
About reference of built operator.
You can reference existing operator< for any class (of course if they are not private, protected or your class/function not friend).
But opeator< for builtin types (bool, short, int, double) it is not possible reference.
Event if not look at C++ standard you can see from my text above.
An extension to the solution provided by fghj, that would work for assignment type operators, such as +=/-=, etc would be to wrap these similarly to the standard variants. You could then do:
#include <iostream>
template <typename T>
struct assign_plus {
void operator() const (T& a, const T& b){
a += b;
}
};
template <typename T>
struct assign_minus {
void operator() const (T& a, const T& b){
a -= b;
}
};
template<template <class T> class O> requires requires(int& a, const int& b){
{ O<int>{}(a,b) };
}
void example(int& a, const int& b){
O<int>{}(a,b);
}
int main(){
int a = 5;
int b = 6;
example<assign_plus>(a,b);
std::cout << a << "\n";
example<assign_minus>(a,b);
std::cout << a << "\n";
return 0;
}
where the constraint could be kept/removed given c++20 compatibility. These constraints then also could be extended to require that a += b is valid (for custom types for example).
I want to refer to function pointers of built-in operators, but I don't know how to specify the specific type overloads.
I have the following template class signature:
template<typename ParamsType, typename FnCompareType>
class MyAction
{
public:
MyAction(ParamsType& arg0, ParamsType& arg1, FnCompareType& fnCpmpare)
: arg0_(arg0), arg1_(arg1), fnCompare_(fnCpmpare) {}
bool operator()()
{
if((*fnCompare_)(arg0_,arg1_)
{
// do this
}
else
{
// do s.th. else
}
}
private:
ParamsType& arg0_;
ParamsType& arg1_;
FnCompareType& fnCompare_;
}
And want to use a syntax like this:
void doConditional(int param1, int param2)
{
MyAction<int,&::operator>=> action(param1,param2);
if(action())
{
// Do this
}
else
{
// Do that
}
}
But that doesn't compile:
error: ‘::operator>=’ has not been declared
What can I do to refer to such intrinsic static operations?
Built-in operators
Why you cannot have function pointers of them:
C++11, §13.6/1, [over.built]
The candidate operator functions that represent the built-in operators defined in Clause 5 are specified in this subclause. These candidate functions participate in the operator overload resolution process as described in 13.3.1.2 and are used for no other purpose.
Built-in operators (those for the built-in types) aren't real operator functions. So you can't have function pointer pointing to them. You also cannot invoke them using operator<(A,B) syntax.
They only participate in overload resolution but the compiler will translate them directly into the appropriate asm/machine instruction without any kind of "function call".
The way to get around this issue:
user1034749 has already answered this question, but for completeness:
The standard defines a lot of function objects in §20.8, [function.objects], i.e.
Arithmetic operations
Comparisons
Logic operations
Bitwise operations
A function object is an object of a function object type. In the places where one would expect to pass a pointer to a function to an algorithmic template (Clause 25), the interface is specified to accept a function object. This not only makes algorithmic templates work with pointers to functions, but also enables them to work with arbitrary function objects.
C++11, §20.8.5, [comparisons]
equal_to
not_equal_to
greater, less
greater_equal
less_equal
Those are templated function objects which decay to the analogous operator in their operator() function. They can be used as function pointer arguments.
user1034749 is right, I want to state: There's no other way, these are completely equivalent in usage to 'raw' function pointers. Reference given.
Standard class type operators
You can use standard library operators as function pointers (which are present as "real functions").
But you'll have to refer to the respective instance of the template. The compiler will need appropriate hints to deduce the correct template.
This works for me on MSVC 2012 using operator+ of std::basic_string
template<class Test>
Test test_function (Test const &a, Test const &b, Test (*FPtr)(Test const &, Test const &))
{
return FPtr(a, b);
}
int main(int argc, char* argv[])
{
typedef std::char_traits<char> traits_t;
typedef std::allocator<char> alloc_t;
std::basic_string<char, traits_t, alloc_t> a("test"), b("test2");
std::cout << test_function<std::basic_string<char, traits_t, alloc_t>>(a, b, &std::operator+) << std::endl;
return 0;
}
If the template argument of test_function is left out to be deduced this will fail (at least for MSVC 2012).
You can use the same solution as used in C++ standard library:
std::sort (numbers, numbers+5, std::greater<int>());
where greater is
template <class T> struct greater : binary_function <T,T,bool> {
bool operator() (const T& x, const T& y) const {return x>y;}
};
in your case http://www.cplusplus.com/reference/functional/greater_equal/
About reference of built operator.
You can reference existing operator< for any class (of course if they are not private, protected or your class/function not friend).
But opeator< for builtin types (bool, short, int, double) it is not possible reference.
Event if not look at C++ standard you can see from my text above.
An extension to the solution provided by fghj, that would work for assignment type operators, such as +=/-=, etc would be to wrap these similarly to the standard variants. You could then do:
#include <iostream>
template <typename T>
struct assign_plus {
void operator() const (T& a, const T& b){
a += b;
}
};
template <typename T>
struct assign_minus {
void operator() const (T& a, const T& b){
a -= b;
}
};
template<template <class T> class O> requires requires(int& a, const int& b){
{ O<int>{}(a,b) };
}
void example(int& a, const int& b){
O<int>{}(a,b);
}
int main(){
int a = 5;
int b = 6;
example<assign_plus>(a,b);
std::cout << a << "\n";
example<assign_minus>(a,b);
std::cout << a << "\n";
return 0;
}
where the constraint could be kept/removed given c++20 compatibility. These constraints then also could be extended to require that a += b is valid (for custom types for example).
As stated in the title, why is this possible? Normally templated functions are unable to determine their return type if it's not among the input arguments and is not specifically stated.
For example:
class Foo {
public:
template<typename T>
operator T() { return T(); }
};
int main() {
Foo instance;
int someInteger = instance;
return 0;
}
Compiles and runs without any issues even though the return type is not explicitly stated anywhere. Is the user-defined conversion operator somehow special with regards to template rules?
I realize that it is syntactically not a return type. Nonetheless, it semantically is. After all, it is the type of the object that gets returned by the operator.
Edit:
The question should probably be "Why can't templated function determine their return type?"
This is invalid:
template <class T>
T sizeGetterFun()
{
return std::numeric_limits<T>::max();
}
int main() {
int maxInt = sizeGetterFun();
double maxDouble = sizeGetterFun();
return 0;
}
This is valid and achieves the same thing as requested from the invalid code.
class Foo {
public:
template<typename T>
operator T()
{
return std::numeric_limits<T>::max();
}
};
Foo sizeGetterFun()
{
return Foo();
}
int main() {
int maxInt = sizeGetterFun();
double maxDouble = sizeGetterFun();
return 0;
}
Why can't the compiler deduce the return type automatically without the need for a dummy class that implements the conversion operator? Are there any problems one can come across when using the second(working) example?
Because you declared a conversion function (template). A conversion function has no return type, and because it is a conversion function, it must return a T.
C++ standard section § 12.3.2 [conversion function] :
A member function of a class X having no parameters with a name of the
form
conversion-function-id:
operator conversion-type-id
conversion-type-id:
type-specifier-seq conversion-declarator opt
conversion-declarator:
ptr-operator conversion-declarator opt
specifies a conversion from X to the type specified by the
conversion-type-id. Such functions are called conversion functions. No return type can be specified.
Note:
If you try to explicit a return type, e.g. :
class Foo {
public:
template<typename T>
int operator T() { return T(); }
};
Then you'll get a compiler error (gcc gives "return type specified for 'operator T' ")
How do I avoid implicit casting on non-constructing functions?
I have a function that takes an integer as a parameter,
but that function will also take characters, bools, and longs.
I believe it does this by implicitly casting them.
How can I avoid this so that the function only accepts parameters of a matching type, and will refuse to compile otherwise?
There is a keyword "explicit" but it does not work on non-constructing functions. :\
what do I do?
The following program compiles, although I'd like it not to:
#include <cstdlib>
//the function signature requires an int
void function(int i);
int main(){
int i{5};
function(i); //<- this is acceptable
char c{'a'};
function(c); //<- I would NOT like this to compile
return EXIT_SUCCESS;
}
void function(int i){return;}
*please be sure to point out any misuse of terminology and assumptions
Define function template which matches all other types:
void function(int); // this will be selected for int only
template <class T>
void function(T) = delete; // C++11
This is because non-template functions with direct matching are always considered first. Then the function template with direct match are considered - so never function<int> will be used. But for anything else, like char, function<char> will be used - and this gives your compilation errrors:
void function(int) {}
template <class T>
void function(T) = delete; // C++11
int main() {
function(1);
function(char(1)); // line 12
}
ERRORS:
prog.cpp: In function 'int main()':
prog.cpp:4:6: error: deleted function 'void function(T) [with T = char]'
prog.cpp:12:20: error: used here
This is C++03 way:
// because this ugly code will give you compilation error for all other types
class DeleteOverload
{
private:
DeleteOverload(void*);
};
template <class T>
void function(T a, DeleteOverload = 0);
void function(int a)
{}
You can't directly, because a char automatically gets promoted to int.
You can resort to a trick though: create a function that takes a char as parameter and don't implement it. It will compile, but you'll get a linker error:
void function(int i)
{
}
void function(char i);
//or, in C++11
void function(char i) = delete;
Calling the function with a char parameter will break the build.
See http://ideone.com/2SRdM
Terminology: non-construcing functions? Do you mean a function that is not a constructor?
8 years later (PRE-C++20, see edit):
The most modern solution, if you don't mind template functions -which you may mind-, is to use a templated function with std::enable_if and std::is_same.
Namely:
// Where we want to only take int
template <class T, std::enable_if_t<std::is_same_v<T,int>,bool> = false>
void func(T x) {
}
EDIT (c++20)
I've recently switched to c++20 and I believe that there is a better way. If your team or you don't use c++20, or are not familiar with the new concepts library, do not use this. This is much nicer and the intended method as outlines in the new c++20 standard, and by the writers of the new feature (read a papers written by Bjarne Stroustrup here.
template <class T>
requires std::same_as(T,int)
void func(T x) {
//...
}
Small Edit (different pattern for concepts)
The following is a much better way, because it explains your reason, to have an explicit int. If you are doing this frequently, and would like a good pattern, I would do the following:
template <class T>
concept explicit_int = std::same_as<T,int>;
template <explicit_int T>
void func(T x) {
}
Small edit 2 (the last I promise)
Also a way to accomplish this possibility:
template <class T>
concept explicit_int = std::same_as<T,int>;
void func(explicit_int auto x) {
}
Here's a general solution that causes an error at compile time if function is called with anything but an int
template <typename T>
struct is_int { static const bool value = false; };
template <>
struct is_int<int> { static const bool value = true; };
template <typename T>
void function(T i) {
static_assert(is_int<T>::value, "argument is not int");
return;
}
int main() {
int i = 5;
char c = 'a';
function(i);
//function(c);
return 0;
}
It works by allowing any type for the argument to function but using is_int as a type-level predicate. The generic implementation of is_int has a false value but the explicit specialization for the int type has value true so that the static assert guarantees that the argument has exactly type int otherwise there is a compile error.
Maybe you can use a struct to make the second function private:
#include <cstdlib>
struct NoCast {
static void function(int i);
private:
static void function(char c);
};
int main(){
int i(5);
NoCast::function(i); //<- this is acceptable
char c('a');
NoCast::function(c); //<- Error
return EXIT_SUCCESS;
}
void NoCast::function(int i){return;}
This won't compile:
prog.cpp: In function ‘int main()’:
prog.cpp:7: error: ‘static void NoCast::function(char)’ is private
prog.cpp:16: error: within this context
For C++14 (and I believe C++11), you can disable copy constructors by overloading rvalue-references as well:
Example:
Say you have a base Binding<C> class, where C is either the base Constraint class, or an inherited class. Say you are storing Binding<C> by value in a vector, and you pass a reference to the binding and you wish to ensure that you do not cause an implicit copy.
You may do so by deleting func(Binding<C>&& x) (per PiotrNycz's example) for rvalue-reference specific cases.
Snippet:
template<typename T>
void overload_info(const T& x) {
cout << "overload: " << "const " << name_trait<T>::name() << "&" << endl;
}
template<typename T>
void overload_info(T&& x) {
cout << "overload: " << name_trait<T>::name() << "&&" << endl;
}
template<typename T>
void disable_implicit_copy(T&& x) = delete;
template<typename T>
void disable_implicit_copy(const T& x) {
cout << "[valid] ";
overload_info<T>(x);
}
...
int main() {
Constraint c;
LinearConstraint lc(1);
Binding<Constraint> bc(&c, {});
Binding<LinearConstraint> blc(&lc, {});
CALL(overload_info<Binding<Constraint>>(bc));
CALL(overload_info<Binding<LinearConstraint>>(blc));
CALL(overload_info<Binding<Constraint>>(blc));
CALL(disable_implicit_copy<Binding<Constraint>>(bc));
// // Causes desired error
// CALL(disable_implicit_copy<Binding<Constraint>>(blc));
}
Output:
>>> overload_info(bc)
overload: T&&
>>> overload_info<Binding<Constraint>>(bc)
overload: const Binding<Constraint>&
>>> overload_info<Binding<LinearConstraint>>(blc)
overload: const Binding<LinearConstraint>&
>>> overload_info<Binding<Constraint>>(blc)
implicit copy: Binding<LinearConstraint> -> Binding<Constraint>
overload: Binding<Constraint>&&
>>> disable_implicit_copy<Binding<Constraint>>(bc)
[valid] overload: const Binding<Constraint>&
Error (with clang-3.9 in bazel, when offending line is uncommented):
cpp_quick/prevent_implicit_conversion.cc:116:8: error: call to deleted function 'disable_implicit_copy'
CALL(disable_implicit_copy<Binding<Constraint>>(blc));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Full Source Code: prevent_implicit_conversion.cc
Well, I was going to answer this with the code below, but even though it works with Visual C++, in the sense of producing the desired compilation error, MinGW g++ 4.7.1 accepts it, and invokes the rvalue reference constructor!
I think it must be a compiler bug, but I could be wrong, so – anyone?
Anyway, here's the code, which may turn out to be a standard-compliant solution (or, it may turn out that that's a thinko on my part!):
#include <iostream>
#include <utility> // std::is_same, std::enable_if
using namespace std;
template< class Type >
struct Boxed
{
Type value;
template< class Arg >
Boxed(
Arg const& v,
typename enable_if< is_same< Type, Arg >::value, Arg >::type* = 0
)
: value( v )
{
wcout << "Generic!" << endl;
}
Boxed( Type&& v ): value( move( v ) )
{
wcout << "Rvalue!" << endl;
}
};
void function( Boxed< int > v ) {}
int main()
{
int i = 5;
function( i ); //<- this is acceptable
char c = 'a';
function( c ); //<- I would NOT like this to compile
}
I first tried PiotrNycz's approach (for C++03, which I'm forced to use for a project), then I tried to find a more general approach and came up with this ForcedType<T> template class.
template <typename T>
struct ForcedType {
ForcedType(T v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2);
T m_v;
};
template <typename T>
struct ForcedType<const T&> {
ForcedType(const T& v): m_v(v) {}
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(const T2&);
const T& m_v;
};
template <typename T>
struct ForcedType<T&> {
ForcedType(T& v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2&);
T& m_v;
};
If I'm not mistaken, those three specializations should cover all common use cases. I'm not sure if a specialization for rvalue-reference (on C++11 onwards) is actually needed or the by-value one suffices.
One would use it like this, in case of a function with 3 parameters whose 3rd parameter doesn't allow implicit conversions:
function(ParamType1 param1, ParamType2 param2, ForcedType<ParamType3> param3);
int x = fromString("test") :could not deduce template argument for 'ValueType'
int x = fromString<int>("test") : works fine as expected
So why does the compiler struggle here? I see it with all kinds of real template functions, not just this silly example. It must be a feature of the language, but what?
You can't deduce based on the return type. You can, however, implement a workaround with similar syntax, using the overloaded cast operator:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
class FromString{
private:
string m_data;
public:
FromString(const char*data) : m_data(data) {}
template<typename T>
operator T(){
T t;
stringstream ss(m_data);
ss >> t;
return t;
}
};
template<> FromString::operator bool(){
return (m_data!="false"); //stupid example
}
int main(){
int ans = FromString("42");
bool t = FromString("true");
bool f = FromString("false");
cout << ans << " " << t << " " << f << endl;
return 0;
}
Output:
42 1 0
C++ doesn't do type inference on the return value. I.e., the fact that it is being assigned to an int isn't used in template parameter deduction.
(Removed edit, since someone else presented the overloaded cast solution already.)
Besides the bad choice for an example (probably makes sense to have int x = to<int>("1235") rather than toString), the problem is that the return type does not participate in overload resolution or type inference[1]. The reason for this is that the expression can be used in many places where the type of the return cannot be deduced:
// assuming template <typename T> T to( std::string ):
//
f( to("123") ); // where there are two overloads f(int), f(double)
int x = 1.5 * to("123"); // T == int? T == double?
to("123"); // now what? returned object can be ignored!
So the decision is that the return type will not take part in overload resolution or type deduction.
[1] There is a single exception to this rule, which is the evaluation of a function pointer with more than one overload, where the overload must be selected by either the destination pointer or an explicit cast, but this is just the one exception and is not used in any other context:
void f();
void f(int);
void g( void (*)() );
void g( void (*)(int) );
void (*p1)() = &f; // overload selected based on destination type
void (*p2)(int) = &f;
g( (void (*)(int))&f ); // overload selected based on explicit cast
It looks like your template has the return type templated which cannot be automatically deduced which is why you need to add it in here.
The return type of a function is dependent on overload resolution, not the other way around.
There is a trick that works though: operator= usually exists only for equal LHS/RHS argument types, except when an explicit operator= is defined (whether as standalone or as a member does not matter).
Thus, overload resolution will find operator=(int &, int), and see if the return value from your function is convertible to int. If you return a temporary that has an operator int, this is an acceptable resolution (even if the operator int is in the generic form of a template<typename T> operator T).
Thus:
template<typename T, typename U>
U convert_impl(T const &t);
template<typename T>
struct convert_result {
convert_result(T const &t) : t(t) { }
template<typename U> operator U(void) const { return convert_impl<U>(t); }
T const &t;
};
template<typename T>
convert_result<T> convert(T const &t) { return t; }