use of + followed by :: (scope resolution operator in C++ code - c++

I have following C++ code snippet :
inline std::vector<std::unique_ptr<xir::Tensor>> cloneTensorBuffer(
const std::vector<const xir::Tensor*>& tensors)
{
auto ret = std::vector<std::unique_ptr<xir::Tensor>>{};
auto type = +::DataType::XINT;
ret.reserve(tensors.size());
for (const auto& tensor : tensors) {
ret.push_back(std::unique_ptr<xir::Tensor>(xir::Tensor::create(
tensor->get_name(), tensor->get_shape(), xir::DataType{type, 8u})));
}
return ret;
}
I am not clear about the statement:
auto type = +::DataType::XINT;
What is meant by + followed by ::(scope resolution operator)?

The combination has no special meaning. + is the regular prefix operator. In this particular case it’s probably redundant, or performs coercion to int. However, the actual meaning might differ depending on how it’s overloaded for the type of ::DataType::XINT.
And :: is regular scope resolution operator. When used at the beginning of a sub-expression (i.e. without a left-hand operand), it causes lookup to be performed at the top scope, i.e. it ignores any shadowing redefinition of DataType in a nested scope:
int x = 1;
void f() {
int x = 2;
std::cout << "inner = " << x << "\n"; // inner = 2
std::cout << "outer = " << ::x << "\n"; // outer = 1
}

There is no +::. Its the unary + operator and :: operator.
::foo refers to foo in the global namespace. It might be necessary when there is another DataTye::XINT in the current namespace.
The unary + is sometimes used to trigger implicit conversions. You need to check what type ::DataType::XINT is and what conversions it has available.
As I don't know what ::DataType::XINT is, here is an example with a lambda expression:
template <typename T>
void foo();
int main() {
auto x = [](){};
foo(x);
foo(+x);
}
Error message (shortened) is:
<source>:6:8: error: no matching function for call to 'foo(main()::<lambda()>&)'
6 | foo(x);
<source>:7:8: error: no matching function for call to 'foo(void (*)())'
7 | foo(+x);
| ~~~^~~~
You can see that foo(x) tries to call foo with the lambda, while in foo(+x) the lambda was implicitly converted to a function pointer (because of ClosureType::operator ret(*)(params)() and + being available for function pointers but not for the lambdas type).

Related

Is it possible to call the << operator using prefix notation?

I am wondering if I could write, for instance: <<(object, cout); or <<(cout,object); where object is a user defined class which has the << operator overloaded, just as one could write:
int a = +(2,3); and obtain the expected result, as in int a = 2 + 3;.
Furthermore, what should one do if this is possible, but requires a few steps? Should one overload the << operator with two different signatures?
just as one could write: int a = +(2,3); and obtain the expected
result, as in int a = 2 + 3;
No, you have a misunderstanding. +(2, 3) will go by the associativity of the comma operator and assign +3 (3) to the variable a.
Therefore, int a = +(2, 3) is the same as int a = 3, and not int a = 2 + 3
I am wondering if I could write, for instance: <<(object, cout); or
<<(cout,object);
No, you can't.
If you want to use the operators in that fashion then you should call its fully qualified name, for example:
operator+ instead of +
operator<< instead of <<
Note:
This will not work for fundamental datatypes. Take care of the class scope and namespaces when you are using the overloaded versions of these operators.
You can do this, e.g.
operator<<(std::cout, "hi");
This expression
int a = +(2, 3);
is not doing operator+. It's first applying the , sequence operator, which gives 3, and then applying unary +, which gives 3.
You can't do this
int a = operator+(2, 3); // error
because ints are fundamental types.
If you have user defined types S, then the following snippets have the same meaning
S s{};
std::cout << s;
auto x = s + s;
is the same as
S s{};
operator<<(std::cout, s);
auto x = operator+(s, s);
assuming the operators are defined for S, the correct operator will be called.

C++ postfix expression undefined vs unspecified behaviour

Apologies in advance, I know the general topic of evaluation order has had a lot of SO questions on it already. However, having looked at them, I want to clarify a few specific points that I don't think amount to a duplication of anything. Suppose I have the following code:
#include <iostream>
auto myLambda(int& n)
{
++n;
return [](int param) { std::cout << "param: " << param << std::endl; };
}
int main()
{
int n{0};
myLambda(n)(n);
return 0;
}
The program above outputs "n: 0" when I compile it. Here we have unspecified ordering at play: it could have just as easily output "n: 1" had a different evaluation order taken place.
My questions are:
What exactly is the sequencing relationship at play during the final function invocation above (i.e. the lambda-expression invocation), between the postfix expression myLambda(0), its argument n, and the subsequent function call itself?
Is the above an example of undefined or unspecified behaviour - and why exactly (with reference to the standard)?
If I changed the lambda code to [](int param) { std::cout << "hello" << std::endl } (i.e. made the outcome independent of its parameter and thus any evaluation order decisions, making behaviour deterministic) would the answer to 2) above still be the same?
EDIT: I've change the lambda parameter name from 'n' to 'param' because that seemed to be causing confusion.
Ironically (since the example uses C++11 features, and other answers have been distracted by that) the logic that makes this sample have unspecified behaviour dates back to C++98, Section 5, para 4
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.
Essentially the same clause exists in all C++ standards although, as noted in comment by Marc van Leeuwen, recent C++ standards no longer use the concept of sequence points. The net effect is the same: within a statement, the order or evaluation of operands of operators and subexpressions of individual expressions remains unspecified.
The unspecified behaviour occurs because an expression n is evaluated twice in the statement
myLambda(n)(n);
One evaluation of the expression n (to obtain a reference) is associated with the first (n) and another evaluation of an expression n (to obtain a value) is associated with the second (n). The order of evaluation of those two expressions (even though they are, optically, both n) is unspecified.
Similar clauses exist in ALL C++ standards, and have the same result - unspecified behaviour on the statement myLambda(n)(n), regardless of how myLambda() implemented
For example, myLambda() could be implemented in C++98 (and all later C++ standards, including C++11 and later) like this
class functor
{
functor() {};
int operator()(int n) { std::cout << "n: " << n << std::endl; };
};
functor myLambda(int &n)
{
++n;
return functor();
}
int main()
{
int n = 0;
myLambda(n)(n);
return 0;
}
since the code in the question is just a (C++11) technique (or shorthand) for achieving the same effect as this.
The above answers OP's questions 1. and 2. The unspecified behaviour occurs in main(), is unrelated to how myLambda() itself is implemented.
To answer the OP's third question, the behaviour is still unspecified if the lambda (or the functor's operator()) in my example) is modified to not access the value of its argument. The only difference is that the program as a whole produces no visible output that might vary between compilers.
The n in the definition of the lambda is a formal argument to the function that the lambda defines. It has no connection to the argument to myLambda that's also named n. The behavior here is dictated entirely by the way these two functions are called. In myLambda(n)(n) the order of evaluation of the two function arguments is unspecified. The lambda can be called with an argument of 0 or 1, depending in the compiler.
If the lambda had been defined with [=n]()... it would behave differently.
I didn't manage to find proper reference to standard but I see that it has similar behavior to argument evaluation order asked here and the order of function arguments evaluation is not defined by the standard:
5.2.2 Function call
8 [ Note: The evaluations of the postfix expression and of the argument expressions are all unsequenced relative to one another. All side effects of argument expression evaluations are sequenced before the function
is entered (see 1.9). —end note ]
So here's how it goes inside the calls on different compilers:
#include <iostream>
#include <functional>
struct Int
{
Int() { std::cout << "Int(): " << v << std::endl; }
Int(const Int& o) { v = o.v; std::cout << "Int(const Int&): " << v << std::endl; }
Int(int o) { v = o; std::cout << "Int(int): " << v << std::endl; }
~Int() { std::cout << "~Int(): " << v << std::endl; }
Int& operator=(const Int& o) { v = o.v; std::cout << "operator= " << v << std::endl; return *this; }
int v;
};
namespace std
{
template<>
Int&& forward<Int>(Int& a) noexcept
{
std::cout << "Int&: " << a.v << std::endl;
return static_cast<Int&&>(a);
}
template<>
Int&& forward<Int>(Int&& a) noexcept
{
std::cout << "Int&&: " << a.v << std::endl;
return static_cast<Int&&>(a);
}
}
std::function<void(Int)> myLambda(Int& n)
{
std::cout << "++n: " << n.v << std::endl;
++n.v;
return [&](Int m) {
std::cout << "n: " << m.v << std::endl;
};
}
int main()
{
Int n(0);
myLambda(n)(n);
return 0;
}
GCC g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out and MSVC
Int(int): 0
Int(const Int&): 0
++n: 0
Int&: 0
Int&: 0
Int(const Int&): 0
n: 0
~Int(): 0
~Int(): 0
~Int(): 1
So it creates variable and copies it to pass to returned lamba.
Clang clang++ -std=c++14 main.cpp && ./a.out
Int(int): 0
++n: 0
Int(const Int&): 1
Int&: 1
Int&: 1
Int(const Int&): 1
n: 1
~Int(): 1
~Int(): 1
~Int(): 1
Here it creates variable evaluates function and then passees copy the lamba.
And the order of evaluation is:
struct A
{
A(int) { std::cout << "1" << std::endl; }
~A() { std::cout << "-1" << std::endl; }
};
struct B
{
B(double) { std::cout << "2" << std::endl; }
~B() { std::cout << "-2" << std::endl; }
};
void f(A, B) { }
int main()
{
f(4, 5.);
}
MSVC and GCC:
2
1
-1
-2
Clang:
1
2
-2
-1
As in clang order is forward and the argument to lambda is passed after evaluation of the function's argument
Ṫhe behaviour is unspecified, because in the function call (myLambda(n))(n) the postfix expression (which I gave an extra redundant pair of parentheses) is unsequenced relative to the argument expression n (the rightmost one). However there is no undefined behaviour, because the modification of n takes place inside the function call myLambda(n). The only definite sequencing relation is that both evaluating myLambda(n) and the final n are obviously sequenced before the actual call of the lambda. For the final question, is the lambda chooses to completely ignore its argument, then the behaviour is no longer unspecified: though it is unspecified what value gets passed as parameter, there is no observable difference either way.
The order in which sub expressions are evaluated is unspecified and can vary apart from the operators &&, ||,? and ",".
The compiler knows both function prototyps myLambda and also the return lambda(extracted from the return type). Cause my first sentence the compiler is free which expression he evaluates first. Thats why you should never call to functions in on expression which have additional side effects.

c++ Need clear examples showing difference between decltype(x) & decltype((x))

I have read many times on the difference between decltype(x) and decltype((x)). One example is as per below.
x is the name of a variable, so decltype(x) is int. But wrapping the name x in parentheses—“(x)”—yields an expression more complicated than a name. Being a name, x is an lvalue, and C++ defines the expression (x) to be an lvalue, too. decltype((x)) is therefore int&. Putting parentheses around a name can change the type that decltype reports for it!
Can someone show me the output of a variable say x where the output type of decltype(x) and decltype((xx)) are different? I need an example explicitly showing difference in output.
Appreciate that.
Thanks.
If you declare a variable with type decltype((x)), it is a reference. The easiest way to see the difference is probably this:
int x = 0;
decltype(x) copy = x; // creates an int which is a copy of x
decltype((x)) ref = x; // creates a reference to x
ref = 7; // changes x
copy = 99; // does not change x
std::cout << x << '\n'; // prints 7
std::cout << copy << '\n'; // prints 99
std::cout << ref << '\n'; // prints 7
As for when you would use decltype((x)), I hesitate to say never, but I can say that I've never had a reason to do it in my own code.
Let's say we have int a = 0, then decltype(a) would be int, since a directly names the entity. decltype((a)), on the other hand, should be int&, since (a) is an expression that does not refer directly to the entity.
The same holds for members as well, for example:
#include <iostream>
#include <type_traits>
struct S {
int v = 0;
};
int main() {
S s;
std::cout << std::is_same<decltype(s.v), int>() << std::endl;
std::cout << std::is_same<decltype((s.v)), int&>() << std::endl;
}
decltype(s.v) is int, since s.v directly refers to the name of an entity. decltype((s.v)), on the other hand, is int&. (s.v) does not refer directly to the name of the entity.

What does it mean in C++ when you have a parameter like ::lower? [duplicate]

This question already has answers here:
What does the "::" mean in "::tolower"?
(4 answers)
scope resolution operator without a scope
(6 answers)
Closed 8 years ago.
On S.O. posts such as How to convert std::string to lower case?, I've seen the syntax ::something, e.g.
std::transform(data.begin(), data.end(), data.begin(), ::tolower);
and I'm wondering what that means. I know that std::transform looks for a function or variable named transform inside the namespace std. But what does the scope operator mean when it doesn't have a first argument?
::tolower
means that tolower would be looked up in global namespace
But what does the scope operator mean when it doesn't have a first
argument?
It denotes the global namespace.
Consider a simple example. Let;s assume that you defined function swap. At the same time you included header <utility> that also contains a declaration of swap. and after it dirrective using namespace std; To distinguihs them you need to use qualified name.
#include <iostream>
#include <utility>
using namespace std;
void swap( int &x, int &y )
{
std::cout << "Inside ::swap" << std::endl;
int tmp = x;
x = y + 10;
y = tmp + 10;
}
int main()
{
int x = 1;
int y = 2;
std::swap( x, y );
std::cout << "x = " << x << ", y = " << y << std::endl;
x = 1;
y = 2;
::swap( x, y );
std::cout << "x = " << x << ", y = " << y << std::endl;
return 0;
}
The output will be
x = 2, y = 1
Inside ::swap
x = 12, y = 11
In this example ::swap refers to your function swap defined in the global namespace while std::swap refers to standard function swap declared in name space std in header <utility>
If you will write unqualified name
swap( x, y );
when the compiler will not know which function to call: either standard function std::swap or your own function ::swap
If to exclude directive
using namepsace std;
and write
swap( x, y );
then the compiler will call your own function swap.
Now I will explain why in your example with standard algorithm std::transform there is used ::tolower. The problem is that in C++ there are two functions with name tolower. One of which is C standard function declared in header <cctype> and other is C++ function declared in header <locale>. The C++ Standard allows to place C standard functions in the global namespace. So using name ::tolower allows the compiler to select the C standard function instead of the C++ function.
The std::transform function iterates over a sequence and applies a transformation function for each element.
The last argument is a so called functor, which may be a function pointer or an object of a class implementing operator(). Functor is a concept very widely applied in algorithm-part of std lib.
e.g.: very useful function converting all characters to a given character:
int testAnywhereInCppCode()
{
struct ToAnotherChar
{
char _toChar;
ToAnotherChar( char toChar):_toChar(toChar){}
char operator()(char c){ return _toChar; }
};
ToAnotherChar toAnotherCharConverter('x');
std::string data = "Hello World";
std::transform(data.begin(), data.end(), data.begin(), toAnotherCharConverter);
return 0;
}
static int testAnywhereInCppCodeCaller = testAnywhereInCppCode();
:: means only the global namespace, where std::toLower is implemented.
However std::toLower is only a standard way to make lower-case. You could implement your own (e.g. for a very exotic charset) and use it with std::transform

Can user defined literals have functions as arguments?

Can functions be used with user defined literals?
If so, what shenanigans can be done? Is this legal?
void operator "" _bar(int (*func)(int)) {
func(1);
}
int foo(int x) {
std::cout << x << std::endl;
}
int main() {
foo(0); // print 0
foo_bar; // print 1
}
According to the C++11 Feb 2011 Draft § 2.14.8, the user literal types are integer-literals, floating-literals, string-literals, and character-literals. There is no way to do a function-literal type.
A user-defined-literal is treated as a call to a literal operator or
literal operator template (13.5.8). To determine the form of this call
for a given user-defined-literal L with ud-suffix X, the
literal-operator-id whose literal suffix identifier is X is looked up
in the context of L using the rules for unqualified name lookup
(3.4.1). Let S be the set of declarations found by this lookup. S
shall not be empty.
Integers:
operator "" X (n ULL)
operator "" X ("n")
operator "" X <’c1’, ’c2’, ... ’ck’>()
Floating:
operator "" X (f L)
operator "" X ("f")
operator "" X <’c1’, ’c2’, ... ’ck’>()
String:
operator "" X (str, len)
operator "" X <’c1’, ’c2’, ... ’ck’>() //unoffcial, a rumored GCC extension
Character:
operator "" X (ch)
Look at foo_bar, its just a single lexical token. Its interpreted as a single identifier named foo_bar, not as foo suffixed with _bar.
No.
C++ intentionally avoids such shenanigans since the symbol foo_bar would be very difficult to comprehend if it weren't defined immediately before its use in your example.
You could achieve something similar with the preprocessor.
#define bar (1)
int foo(int x) {
std::cout << x << std::endl;
}
int main() {
foo(0); // print 0
foo bar; // print 1
}
I don't know if this adds anything but there's nothing preventing you from defining
PythonScript operator"" _python(const char*, std::size_t len) {...}
R"Py(
print "Hello, World"
)Py"_python;
I actually think user-defined literals would make a nice way to embed scripts or SQL.