#Python code
user = input("Please enter your name \n")
print ("Your name is,", user)
How can I make this in C++?
I don't exactly know what you want to achieve, but I think this is what you're looking for.
#include<iostream>
#include<string>
using namespace std;
int main()
{
string user;
/* ---- This part is in place of your python code --- */
cout << "Please Enter your name"; cin >> user;
cout << "Your name is" << user;
/* --------------------- */
return 0;
}
Unfortunately, the accepted answer does not match the legitimate question, how to realize the input.
Consider this solution:
#include <iostream>
#include <string>
template<typename T>
T input(std::string message = "")
{
if (!empty(message)) std::cout << message << " : ";
T value;
std::cin >> value;
return value;
}
int main()
{
auto i = input<int>("integer, followed by decimal point value");
auto d = input<double>();
if (std::cin) std::cout << "Gelesen: " << i << ' ' << d << '\n';
else std::cout << "error reading input";
}
The input() function does not return a string like in Python, but a value of the type indicated in angle brackets.
Related
I have a templated class MyClass<T> that takes some iterable containing ints (e.g. T = std::vector<int>) in its constructor and does something with it.
I would like to be able to pass the iterable as either a temporary object (e.g. MyClass(std::vector<int>{3,6,9}) or similar r-value argument) or from a named variable (resulting in an l-value as the constructor argument).
I would like to use C++17 template class inference (i.e. write MyClass(...), not MyClass<std::vector<int>>(...)).
I thought that I could declare the constructor parameter as MyClass(T && vec) (a "universal reference") to take either an l-value or an r-value (just like I can with functions), but it gives an error. It seems like T is always inferred as std::vector<int> and never std::vector<int>& with classes, whereas functions infer std::vector<int>& when the argument is an l-value.
How exactly are the rules for template constructor inference and template function inference different? Can I avoid having to use a wrapper function (e.g. myFunction(T&&vec) { return MyClass<T>(std::forward<T>(vec)); }) just for the sake of template inference?
Run the code below on Godbolt:
#include <iostream>
#include <utility>
#include <vector>
template <typename T>
using BeginType = decltype(std::declval<T>().begin());
template <typename T>
struct MyClass {
BeginType<T> begin;
BeginType<T> end;
MyClass(T && vec) {
begin = std::forward<T>(vec).begin();
end = std::forward<T>(vec).end();
}
int sum() {
int sum = 0;
for (auto it = begin; it != end; ++it) sum += *it;
return sum;
}
};
template <typename T>
MyClass<T> myFunction(T && vec) {
return MyClass<T>(std::forward<T>(vec));
}
int main() {
std::vector<int> x{1, 2, 3};
std::vector<int> y{2, 4, 6};
// Warmup: Passing r-values works fine
std::cout << MyClass(std::vector<int>{3, 6, 9}).sum() << std::endl; // works fine: T is std::vector<int>
std::cout << MyClass(std::move(y)).sum() << std::endl; // works fine: T is std::vector<int>
// Unexpected: Passing l-values doesn't work
// std::cout << MyClass(x).sum() << std::endl; // error: cannot bind rvalue reference of type 'std::vector<int>&&' to lvalue of type 'std::vector<int>'
// Compare: Passing l-values to function works fine
std::cout << myFunction(x).sum() << std::endl; // works fine: T is std::vector<int>&
}
Add a user-defined deduction guide after the class definition:
template <typename T>
struct MyClass {
// same as in question
};
template <typename TT> MyClass(TT && vec) -> MyClass<TT>;
See also How to write a constructor for a template class using universal reference arguments in C++
I am confused with some aspects of the implicit move constructor.
My understanding is that the implicitly-declared move constructor are provided by the compiler for a class iff there are no user-declared copy constructors, no copy assignment operators, no move assignment operators and no destructors.
This is the case with 'Heavy' in my example. Which behaves as expected (data is moved).
'HeavyWithDestructor' would not qualify for a implicitly-declared move constructor, because it has a destructor, but I can "std::move" it. Sort of, it is a copy (see the data pointer).
This looks to me like a trivial move constructor, in the sense that it performs the same actions as the trivial copy constructor (as if by std::memmove).
But if I don't have the conditions for the creation of a implicit move constructor in the first place, how can it be a trivial move constructor. Further more, 'std::is_trivially_move_constructible_v' indicates this is not a trivial move constructor.
#include <iostream>
#include <vector>
#include <type_traits>
using namespace std;
constexpr int largeNumber = 10000000;
#define OUT(...) std::cout << #__VA_ARGS__ << " : " << __VA_ARGS__ << '\n'
// Consistent with an implicit 'move' constructor.
class Heavy
{
vector<int> v_;
public:
Heavy() : v_(vector<int>(largeNumber)) {}
int* getDatap() { return v_.data(); }
};
// Not consistent with an implicit 'move' constructor. (Because has a destructor)
class HeavyWithDestructor
{
vector<int> v_;
public:
HeavyWithDestructor() : v_(vector<int>(largeNumber)) {}
~HeavyWithDestructor(){}
int* getDatap() { return v_.data(); }
};
int main()
{
cout << "Moving a heavy object" << endl;
OUT(std::is_move_constructible_v<Heavy>);
OUT(std::is_trivially_move_constructible_v<Heavy>);
Heavy originalHeavy;
cout << "Data* in original() -> " << originalHeavy.getDatap() << endl;
Heavy finalHeavy = move(originalHeavy);
cout << "Data* in main() -> " << finalHeavy.getDatap() << endl << endl;
cout << "Moving a heavy object with a destructor" << endl;
OUT(std::is_move_constructible_v<HeavyWithDestructor>);
OUT(std::is_trivially_move_constructible_v<HeavyWithDestructor>);
HeavyWithDestructor originalWoDestructor;
cout << "Data* in original() -> " << originalWoDestructor.getDatap() << endl;
HeavyWithDestructor finalWoDestructor = move(originalWoDestructor);
cout << "Data* in main() -> " << finalWoDestructor.getDatap() << endl;
return 0;
}
I get the following output: I can confirm I am moving 'Heavy' cause the pointers to the vector data point to the same location. I can also confirm that 'HeavyWithDestructor' is copying, not moving the data.
Moving a heavy object
std::is_move_constructible_v<Heavy> : 1
std::is_trivially_move_constructible_v<Heavy> : 0
Data* in original() -> 000001E3FB193080
Data* in main() -> 000001E3FB193080
Moving a heavy object with a destructor
std::is_move_constructible_v<HeavyWithDestructor> : 1
std::is_trivially_move_constructible_v<HeavyWithDestructor> : 0
Data* in original() -> 000001E3FD7C6080
Data* in main() -> 000001E38000A080
What is this constructor that the compiler is declaring for 'HeavyWithDestructor'?. If this constructor is not moving the data, why can I still use std::move on it?
If I try harder to make the compiler NOT declare a move constructor for me by defining a copy constructor, then I cannot use the std::move. I get compilation errors. This is what I would expect. From this, I gather the constructor I am getting is not a copy constructor. From where I initially suspected this is a trivial move constructor (that behaves as in std::memmove), but I have indications that is not right either. So what is this?
I am using vs2019 c++17 as a compiler.
HeavyWithDestructor is a typical C++03 type: copyable but not movable (what’s “movable”?). As such, for compatibility, it is copied whenever a move is attempted. The technical reason for this is that const HeavyWithDestructor& can bind to an rvalue; the moral reason is that std::move, as always, grants permission to move something but does not require it (or do so itself).
(Your experiment with a copy constructor is not detailed enough to reproduce, but might have involved HeavyWithDestructor(HeavyWithDestructor&) that is still considered a copy constructor but cannot serve as a move constructor.)
If I have a templated class, I can do the following to detect if a vector was passed:
template<typename T> struct is_vector { static const bool value=false; };
template<typename T> struct is_vector<std::vector<T>> { static const bool value=true; };
template<class T>
class Parser {
public:
Parser() {}
void parse(T obj) {
if (is_vector<T>::value) {
std::cout << "vector\n";
//obj.push_back(T {});
}
else {
std::cout << "not vector\n";
}
}
};
int main() {
Parser<int> p1;
p1.parse(123);
Parser<std::vector<int>> p2;
p2.parse({ 1, 2, 3});
return 0;
}
Output:
not vector
vector
I can detect a vector, yet the compiler complains when I uncomment the push_back call:
main.cpp: In instantiation of ‘void Parser<T>::parse(T) [with T = int]’:
main.cpp:26:14: required from here
main.cpp:15:17: error: request for member ‘push_back’ in ‘obj’, which is of non-class type ‘int’
obj.push_back(T {});
~~~~^~~~~~~~~
Obviously, an int does not have a push_back function, but the vector does. The is_vector call is evaluated at runtime, but the push_back is caught at compile time.
With partial template specialization, I can do what I want:
template<typename T>
void parse(T obj) {
std::cout << "not vector: " << obj << "\n";
}
template<typename T>
void parse(std::vector<T> obj) {
std::cout << "is vector\n";
for (auto i : obj) std::cout << i << " ";
obj.push_back(T {});
std::cout << "\n";
for (auto i : obj) std::cout << i << " ";
std::cout << "\n";
}
int main() {
parse(1);
parse('a');
parse(std::vector<int> { 1, 2, 3 });
return 0;
}
Output:
not vector: 1
not vector: a
is vector
1 2 3
1 2 3 0
So, how can I combine these 2 ideas, either at compile-time or at runtime? That is, have a templated class with a function that can handle vectors and non-vectors?
What you're looking for is a new feature in C++17, if constexpr. It's the same as a regular if, except that the condition is evaluated at compile time, and when instantiating the branch(es) will discard the non-taken branch at compile time. The discarded branch does not need to well-formed. So, for your example:
template<class T>
class Parser {
public:
Parser() {}
void parse(T obj) {
if constexpr (is_vector<T>::value) {
std::cout << "vector\n";
obj.push_back(T {});
}
else {
std::cout << "not vector\n";
}
}
};
See Difference between if constexpr vs if for some more talk on the differences. You can also read the cppreference page on if statements to get a detailed overview of some of the nitty-gritty details.
This question already has answers here:
How to check whether operator== exists?
(14 answers)
Closed 3 years ago.
I am writing code to compare to instances of various types. The final comparison function is quite simple - with signature:
template <typename T>
int not_equal(const T& arg1, const T& arg2) {
if (arg1 == arg2)
return 0;
std::cerr << "Error when comparing" << std::endl;
return 1;
}
Now - I would like to add the actual values being compared in the std::cerr message as:
std::cerr << "Error when comparing " << arg1 << " != " << arg2 << std::endl;
however - many of the classes do not have operator<< - and that is OK. For the classes which do not support operator<< I just want the classname - i.e. the pseudo code should be something like:
if (supports_operator<<<T>)
std::cerr << "Error when comparing " << arg1 << " != " << arg2 << std::endl;
else
std::cerr << "Error when comparing instances of type: " << typeid(arg1).name() << std::endl;
Can I have my fictitious supports_operator<<<T>()functionality?
Edit: I am limited to C++17
If you are able to use C++20 and concepts, then you can do something like this:
#include <iostream>
#include <concepts>
template <typename T>
concept Streamable = requires (T x) { std::cout << x; };
struct Foo {};
struct Bar {};
std::ostream& operator<<(std::ostream& os, Foo const& obj) {
// write obj to stream
return os;
}
template <Streamable T>
void foo(T const& t) {
std::cout << t << std::endl;
}
int main() {
Foo f;
Bar b;
foo(f);
foo(b); // error
return 0;
}
Demo
I have been using an indicator to take trades. I didn't develop the indicator, so I only have access to the .ex4 file. How can I extract the take profit, open trade and stop loss values in the alerts or email signals to open trades? Please see a sample of the email and alert signals below.
Here is a working example script of a native MQL solution which uses kernel32.dll to copy the log file from ./MQL4/Logs to ./MQL4/Files. The LogSignalParser abstract base class needs to be subclassed and requires implementation of the virtual bool parse() method.
Edit: #TenOutOfTen would like a practical example of how to parse the following row format in a log file:
0 02:20:00.874 SuperIndicator USDCAD,M5: Alert: USDCAD, M5: Super Indicator SELL # 1.29136, TP 1.28836, SL 1.29286
Step 1: Save the LogParser.mqh somewhere meaningful.
//LogParser.mqh
#property strict
#include <stdlib.mqh>
#include <Arrays\ArrayString.mqh>
#include <Arrays\ArrayObj.mqh>
#import "kernel32.dll"
bool CopyFileW(string lpExistingFileName,
string lpNewFileName,
bool bFailIfExists);
#import
//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+
class Signal : public CObject
{
public:
string symbol;
datetime signal_time;
int order_type;
double price_entry;
double price_sl;
double price_tp;
virtual int Compare(const CObject *node,const int mode=0) const override
{
const Signal *other=node;
if(this.signal_time>other.signal_time)
return 1;
if(this.signal_time<other.signal_time)
return -1;
return 0;
}
string to_string()
{
return StringFormat("%s - %s(%s) # %.5f, SL=%.5f, TP=%.5f",
signal_time,
symbol,
order_type==OP_BUYLIMIT ? "BUY" : "SELL",
price_entry,
price_sl,
price_tp
);
}
};
//+------------------------------------------------------------------+
//|Vector-like collection
//+------------------------------------------------------------------+
class SignalList : public CArrayObj
{
public: Signal *operator[](int i){return this.At(i);}
};
//+------------------------------------------------------------------+
//|Abstract abse class: the parse method must be implemented in subclass
//+------------------------------------------------------------------+
class LogSignalParser : public CObject
{
protected:
CArrayString m_rows;
SignalList m_signals;
string m_log_file_name;
string m_ind_name;
public:
LogSignalParser(string indicator_name);
// parse method must be overridden!
virtual bool parse() = 0;
int Total();
Signal *operator[](int i);
protected:
bool _copy_log();
int _open_log();
bool _parse_rows();
};
//+------------------------------------------------------------------+
LogSignalParser::LogSignalParser(string indicator_name)
{
m_log_file_name="copy_log.log";
m_ind_name=indicator_name;
}
//+------------------------------------------------------------------+
bool LogSignalParser::_copy_log(void)
{
MqlDateTime t;
TimeLocal(t);
string data_path = TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL4";
string logs_path = data_path + "\\Logs\\";
string dest_file = data_path + "\\Files\\" + m_log_file_name;
string log_file=logs_path+StringFormat("%d%02d%02d.log",
t.year,t.mon,t.day);
return CopyFileW(log_file, dest_file, false);
}
//+------------------------------------------------------------------+
bool LogSignalParser::_parse_rows()
{
if(!this._copy_log())
return false;
int h= this._open_log();
if(h == INVALID_HANDLE)
return false;
m_rows.Clear();
while(!FileIsEnding(h)){
string row=FileReadString(h);
if(StringFind(row,"Alert:") >= 0 && StringFind(row,m_ind_name) >= 0)
m_rows.Add(row);
}
m_rows.Sort();
FileClose(h);
return true;
}
//+------------------------------------------------------------------+
int LogSignalParser::_open_log(void)
{
return FileOpen(m_log_file_name,
FILE_TXT|FILE_READ|FILE_SHARE_READ|FILE_SHARE_WRITE);
}
//+------------------------------------------------------------------+
int LogSignalParser::Total(void)
{
return m_signals.Total();
}
//+------------------------------------------------------------------+
Signal* LogSignalParser::operator[](int i)
{
return m_signals.At(i);
}
Step 2: Subclass the LogSignalParser class and override parse
//SuperIndicatorParser.mqh
#property strict
#include "LogParser.mqh"
//+------------------------------------------------------------------+
class SuperIndicatorParser : public LogSignalParser
{
public:
SuperIndicatorParser():LogSignalParser("SuperIndicator"){}
virtual bool parse() override;
};
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
bool SuperIndicatorParser::parse() override
{
if(!this._parse_rows())
return false;
m_signals.Clear();
MqlDateTime local;
TimeLocal(local);
for(int i=m_rows.Total()-1; i>=0; i--)
{
string row=m_rows[i];
MqlDateTime log_time;
TimeToStruct(StringToTime(StringSubstr(row, 2, 12)), log_time);
log_time.year = local.year;
log_time.mon = local.mon;
log_time.day = local.day;
datetime time = StructToTime(log_time);
row = StringSubstr(row, StringFind(row, m_ind_name) + StringLen(m_ind_name) + 1);
StringReplace(row, ",", " ");
string parts[];
StringSplit(row, ' ', parts);
int len = ArraySize(parts);
string debug = "";
for(int k=0;k<len;k++)
debug += "|" + parts[k];
if(len != 17)
continue;
Signal *s = new Signal();
s.signal_time = time;
s.symbol = parts[0];
s.order_type = parts[8] == "BUY" ? OP_BUYLIMIT : OP_SELLLIMIT;
s.price_entry = double(parts[10]);
s.price_tp = double(parts[13]);
s.price_sl = double(parts[16]);
m_signals.Add(s);
}
m_signals.Sort();
return true;
}
Step 3: Use in MQL program (example script)
#property strict
#include "SuperIndicatorParser.mqh"
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
SuperIndicatorParser parser;
if(parser.parse()){
for(int i=parser.Total()-1; i>=0; i--){
Signal *s = parser[i];
int ticket = OrderSend(
s.symbol, s.order_type, 0.1,
s.price_entry, 0, s.price_sl, s.price_tp
);
if(ticket < 0){
Print(_LastError);
}
}
}
}
There's no need to pull the data from your email since the indicator is also sending the data via the Alert function. Alerts are logged to the .\MQL4\Logs directory in a *.log text file. You could write some MQL which uses win32 to read the log, and then make your own parser in MQL.
Another option is to write a watchdog script to scan and parse the log file and write the results to a csv where the EA can access it. The benefit of this method is how easy it is to develop compared to an MQL solution and since it works for all symbols it avoids a potential race condition where multiple EAs are trying to read log write csv at the same time.
Here is an example written in Python.
import csv
import re
import time
from datetime import datetime
from pathlib import Path
MQL_DATA_PATH = Path(
'C:/Users/user/Desktop/MT-TEST/Vanilla-MT4-v0_0_2/MT4/MQL4'
)
OUTPUT_FILENAME = 'signals.csv'
signal_pattern = re.compile(r'''# regex - verbose mode
(?P<time>\d\d:\d\d:\d\d).*? # time stamp
(?P<symbol>[A-Z]{6}\w*),.*? # symbol with ECN suffix
(?P<type>BUY|SELL).*? # BUY or SELL command
(?P<price>\d+\.\d+).*? # execution price
(?P<tp>\d+\.\d+).*? # takeprofit
(?P<sl>\d+\.\d+) # stoploss
''', re.VERBOSE)
def log_to_csv():
date = datetime.now()
log_file = MQL_DATA_PATH / 'Logs' / f'{date.strftime("%Y%m%d")}.log'
with open(log_file) as f:
log_entries = f.read()
signals = [s.groupdict() for s in signal_pattern.finditer(log_entries)]
for signal in signals:
# correct time to MQL datetime
signal['time'] = f"{date.strftime('%Y.%m.%d')} {signal['time']}"
csv_file = MQL_DATA_PATH / 'Files' / OUTPUT_FILENAME
with open(csv_file, 'w') as f:
writer = csv.DictWriter(f,
fieldnames=('time', 'symbol', 'type', 'price', 'tp', 'sl',),
lineterminator='\n',
)
writer.writerows(signals)
def main():
print(f'Watching MQL log and saving signals to {OUTPUT_FILENAME}')
print('Press Ctrl+C to exit')
while True:
try:
log_to_csv()
print(datetime.now().strftime('%Y.%m.%d %H:%M:%S'), end='\r')
time.sleep(5)
except KeyboardInterrupt:
exit()
if __name__ == '__main__':
main()
MT4 cannot read your emails. You need to employ some other tools or a more universal language to read your emails, Java.Mail.API or Pyhton, or something else.
Read the email, make sure the the format is correct and it is from the sender you are expecting, then put down the message into a file that is available to MT4 - either own folder (C:\Users\UserName\AppData\Roaming\MetaQuotes\Terminal\12345678E7E35342DB4776F5AE09D64B\MQL4\Files) or Common folder (C:\Users\User1\AppData\Roaming\MetaQuotes\Terminal\Common\Files). Then read the file from the MT4 application using FileSearchNext() function and example in MQL4 docs. After reading the file, you need to parse it with the String functions, and create a OrderSend() request (probably check the input and that your logic allows your robot to send a trade, e.g. you do not have reached maximum of allowed open trades, trading time, other logic).