Can we send pair a template argumrent another pair - c++

Can we use pair as an argument for another pair in C++.
Here is a test program to do that.
#include <iostream>
#include <utility>
int main()
{
std::pair<int,int> m;
m=std::make_pair(1,3);
int r = 3;
int *q = &r;
int **p =&q;
int **t = p;
std::pair<int**,<std::pair<int,int> > > i(p,m);
std::cout<<i[t];
return 0;
}
This is the error, I am getting.
Test.cpp: In function ‘int main()’:
Test.cpp:12:45: error: template argument 2 is invalid
std::pair<int**,<std::pair<int,int>>> i(p,m);
^
If I changed the format of declaration and wrote the program in the following way,
#include <iostream>
#include <utility>
int main()
{
std::pair<int,int> m;
m=std::make_pair(1,3);
int r = 3;
int *q = &r;
int **p =&q;
int **t = p;
std::pair<
int**,
<
std::pair<
int,
int
>
>
> i(p,m);
std::cout<<i[t];
return 0;
}
There is an additional error.
Test.cpp: In function ‘int main()’:
Test.cpp:20:7: error: template argument 2 is invalid
> i(p,m);
^
Test.cpp:20:14: error: expression list treated as compound expression in initializer [-fpermissive]
> i(p,m);
What might be the issue and how to solve it?
On a side note, I did a program and compiled it in an very old Dev-c++ compiler on a windows 7 machine which used a code similar to the above and it ran perfectly fine. It was a lab program in my college which had only that compiler.
The above code, I ran on both windows 7 and Ubuntu 16.04 using GNU g++ 5.4.0
Ideone: Link to the actual program for reference
You might also have a look at the actual error, I faced in the above link.

This is incorrect:
std::pair<int**,<std::pair<int,int> > > i(p,m);
Just remove the extra <>:
std::pair<int**, std::pair<int,int > > i(p,m);
Also, I'm not sure what you're trying to do in the cout part, but pair doesn't have a [] operator. You can access the elements with first and second:
i.first
i.second
i.second.first
i.second.second
You may also be interested in std::tuple if you don't want to nest one pair into another:
std::tuple<int**, int, int> i;

There are two problems with your code.
You have a superfluous pair of angle brackets in your template instantiation.
The cout parameter makes no sense
#include <iostream>
#include <utility>
int main()
{
std::pair<int,int> m;
m=std::make_pair(1,3);
int r = 3;
int *q = &r;
int **p =&q;
int **t = p;
std::pair<
int**,
// < Omit this
std::pair<
int,
int
>
// > also this
> i(p,m);
// std::cout<<i.[t]; indexing with a pointer value doesn't make sense
// i. for a pair doesn't make sense, specify either first or second
std::cout<<i.first[0]; // <<<< Did you mean something like this?
return 0;
}
Check the compiling version live

Related

std::compare_exchange int with #define value

I want to use std::compare_exchange_strong for some std::atomic<int>
For compilation reasons (int &) I am forced to introduce int _OLD_VALUE = OLD_VALUE.
Is there a more elegant way to achieve this?
Here is my example
#include <atomic>
#include <stdio.h>
#define OLD_VALUE 16
#define NEW_VALUE 744
#define OTHER_VALUE 80
int main(int argc, char **argv)
{
std::atomic<int> i(OTHER_VALUE);
int _OLD_VALUE = OLD_VALUE;
bool status = i.compare_exchange_strong(_OLD_VALUE,NEW_VALUE);
// bool status = i.compare_exchange_strong( OLD_VALUE,NEW_VALUE);
if (status) { printf("good\n"); }
return 0;
}
And here is the compilation error when I use the commented version:
main.cpp: In function ‘int main(int, char**)’:
main.cpp:11:65: error: cannot bind non-const lvalue reference of type ‘std::__atomic_base<int>::__int_type& {aka int&}’ to an rvalue of type ‘int’
bool status = i.compare_exchange_strong( OLD_VALUE,NEW_VALUE);
^
In file included from /usr/include/c++/7/atomic:41:0,
from main.cpp:1:
/usr/include/c++/7/bits/atomic_base.h:496:7: note: initializing argument 1 of ‘bool std::__atomic_base<_IntTp>::compare_exchange_strong(std::__atomic_base<_IntTp>::__int_type&, std::__atomic_base<_IntTp>::__int_type, std::memory_order) [with _ITp = int; std::__atomic_base<_IntTp>::__int_type = int; std::memory_order = std::memory_order]’
compare_exchange_strong(__int_type& __i1, __int_type __i2,
^~~~~~~~~~~~~~~~~~~~~~~
No. The reason being is that the previous value of the variable is exchanged so the expected value is overwritten if the compare mismatches.
To see what's going on under the hood, look at the GCC built-ins:
https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
You will note there is a __atomic_exchange_n in the builtins for GCC (Linux) but that simply provides an exchange as opposed to a compare-and-swap. The Windows equivalent is InterlockedExchange : https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-interlockedexchange
For the sake of readability I would avoid using capitals in variable names and avoid leading underscores:
int oldValue = OLD_VALUE;
The simplest way (and I suppose the only way) to achieve this is to just write simple wrapper:
bool cas_strong(std::atomic<int>& a, int cmp, int exc) {
return a.compare_exchange_strong(cmp, exc);
}
compare_exchange_strong expects an int& to store the current value found in i. Here, you provide indirectly 16 (that is what your macro OLD_VALUE is replaced with at pre-processing), which is an integer compile-time constant, a.k.a. constexpr int&. This is not compatible with int&.
To provide an int&, you should better keep an int near your call of compare_exchange_strong:
std::atomic<int> i(OTHER_VALUE);
int old_value = OLD_VALUE;
bool status = i.compare_exchange_strong(old_value, NEW_VALUE);
if (status) { printf("good\n"); }
return 0;
Also, more generally, it is clearly more powerful if you used static constants instead of macros here.
More on this in this other question: What is the difference between a macro and a const in C++?
Don't use macros to define the values:
#include <atomic>
#include <stdio.h>
int OLD_VALUE 16
int NEW_VALUE 744
int OTHER_VALUE 80
int main(int argc, char **argv)
{
std::atomic<int> i(OTHER_VALUE);
bool status = i.compare_exchange_strong( OLD_VALUE,NEW_VALUE);
if (status) { printf("good\n"); }
return 0;
}

Error using string::erase in C++

I'm having an error while compiling my C++ program. Below is my code!
#include <pthread.h>
#include "Path.h"
#include "Maze.h"
#include "SubmitMazeSoln.h"
#include "Assignm3_Utils.h"
#include "Assignm3.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
srand(time(NULL));
string random = "0123";
for (int i = 0; i < 4; i++)
{
int x = (rand () % random.size());
char y = random[x];
random.erase(remove(random.begin(), random.end() + y), random.end());
int temp;
if (threadData.threadIDArrayIndex == 0)
{
temp = i;
}
else
{
temp = y - '0';
}
}
The error when I compile my program.
myprog.cpp: In function ‘void* exploreMaze(void*)’:
myprog.cpp:108:56: error: cannot convert ‘std::basic_string<char>::iterator {aka __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >}’ to ‘const char*’ for argument ‘1’ to ‘int remove(const char*)’
random.erase(remove(random.begin(), random.end() + y), random.end());
Sorry guys help is deeply appreciated! Thanks!
As DaveB says,
remove(random.begin(), random.end() + y)
should be
remove(random.begin(), random.end(), y)
The error message is confusing because random.end() + y is a valid expression, although it produces an iterator that's way off the end of the container. So the compiler sees a call to the function remove with two arguments, and tries to make sense of it. The compiler sees a function with the signature remove(const char*), and guesses that that's what you meant, then complains that it can't convert the first argument to type const char*.
This confusion wouldn't have happened if you used proper C++ standard library names such as std::remove. using namespace std; strikes again!

Unordered_map<string, int> works but Unordered_map<string, string> does not

I don't understand why the second block of code in this short example does not compile correctly. It is my understanding that the second parameter in the <> represents the value, which doesn't need to be unique. Why is the second block of code throwing a compiler error, and what do I need to do to remedy it?
// Unordered Map example .cpp
#include <stdio.h>
#include <string>
#include <cstring>
#include <unordered_map>
using namespace std;
int main(void) {
// This works as expected
unordered_map<std::string, int> m;
m["foo"] = 42;
printf("%i\n", m["foo"]);
// This this doesn't compile
unordered_map<std::string, std::string> m1;
m1["foo"] = "42";
printf("%s\n", m1["foo"]);
return 0;
}
I am compiling this code on CentOS 5.8 using
g++44 -c -Wall -std=c++0x -g map_example.cpp
and these are the errors I am getting
map_example.cpp: In function ‘int main()’:
map_example.cpp:20: warning: cannot pass objects of non-POD type ‘struct std::basic_string<char, std::char_traits<char>, std::allocator<char> >’ through ‘...’; call will abort at runtime
map_example.cpp:20: warning: format ‘%s’ expects type ‘char*’, but argument 2 has type ‘int’
If I am having trouble with a basic c++ class such a std:string what do I need to do to have a custom class as a value, where can I find a fully implemented minimal example?
printf does not work with std::string. Either use cout << m1["foo"] or printf("%s", m1["foo"].c_str())
printf("%s\n", m1["foo"]); is C.
For c++ you should use std::cout to have both the string and the int map's values printed out as expected.
The compiler cannot do a translation for a std::string object automatically to const char* (there is no conversion to const char* by default: Why does std::string not provide a conversion to const char*?)

Using an array as a map key is not working with C++ 11 compiler command?

I need to use an array as the map key, but I receive compiler errors indicating that the map declaration does not name a type.
I use the code in a similar question, but the code does not compile even when I have chosen the -std=c++0x or -std=c++11 compiler commands.
The code I used is:
typedef std::array<unsigned int, 3> alphabet;
std::map<alphabet, std::string> dictionary;
dictionary[{{1, 0, 8}}] = "hello";
The error is:
error: 'dictionary' does not name a type| error: expected
unqualified-id before ']' token| ||=== Build finished: 2 errors, 0
warnings (0 minutes, 1 seconds) ===|
I see little on this topic even when searching Google. I am using CodeBlocks as my IDE and chosen the compiler commands mentioned above.
I think the error may be because you're trying to assign to dictionary in file scope. As pointed out, variables should be initialized in global scope, i.e.:
std::map<alphabet, std::string> dictionary = { {{1,0,8}, "hello"} };
Otherwise, you should put it in block scope, i.e. in a main().
#include <array>
#include <map>
typedef std::array<unsigned int, 3> alphabet;
std::map<alphabet, std::string> dictionary;
int main()
{
dictionary[{{1, 0, 8}}] = "hello";
}
As a side note, it seems that the braces can be elided. You do not need two sets of braces. dictionary[{1, 0, 8}] will suffice.
How you compare the arrays for the map sort?
I guess you should supply compare method like this:
struct ltarray
{
bool operator()(const alphabet& s1, const alphabet& s2) const
{
//how you compare???
return (s1<s2);
}
};
and you need to init your map template with the compare method:
std::map<alphabet, std::string, ltarray> dictionary;

C++ lambda expression does not compile

I am trying to cin a loop index's value in the loop itself using lambda expression:
#include<iostream>
using namespace std;
int main(){
for(int a, ([](int & b){cin>>b;})(a); a < 2; ++a);
return 0;
}
These are the errors when i compile using g++ 4.5 on ubuntu:
forLoopAndCinTest.c++: In function ‘int main()’:
forLoopAndCinTest.c++:5:14: error: expected unqualified-id before ‘[’ token
forLoopAndCinTest.c++:5:14: error: expected ‘)’ before ‘[’ token
forLoopAndCinTest.c++:5:34: error: expected primary-expression before ‘)’ token
forLoopAndCinTest.c++:5:34: error: expected ‘;’ before ‘)’ token
forLoopAndCinTest.c++:5:40: error: name lookup of ‘a’ changed for ISO ‘for’ scoping
forLoopAndCinTest.c++:5:40: note: (if you use ‘-fpermissive’ G++ will accept your code)
forLoopAndCinTest.c++:5:50: error: expected ‘;’ before ‘)’ token
If i use a normal function instead of the lambda, program compiles fine.
Using -fpermissive doesnt help either.
Any ideas?
That's not how the for look works. You are trying to call a lambda where the compiler expects you to declare an int:
for( int a, int2, ...; a < 2; ++a );
Now,
If i use a normal function instead of
the lambda, program compiles fine
Yes, but it's probably not doing what you think it does.
void f(int& b)
{
cin >> b;
}
// ...
for( int a, f(a); a < 2; ++a );
Here, the loop declares two int variables, named a and f. The loop doesn't call f() as you might expect.
Try this instead:
for( int a; cin >> a && a < 2; ++a );
The first part of the for is interpreted as a declaration. We get the very same error when replacing your code by the (almost) equivalent :
int main(){
int a, ([](int & b){cin>>b;})(a); // This produces the same error
for(; a < 2; ++a);
return 0;
}
To answer a comment you made, for (int a, foo() ; ... works, but not like you think it does. It is in fact declaring a function (inside the for scope) that returns an int, and has the name foo. As in :
int a, foo();
Which you should read as :
int a;
int foo();
After this: for( int a, compiler expects some name (of the variable) - unqualified-id.
But in your case it is not so.