Why there are two different answer in same compare template function - c++11

When I try to implement a template to compare two variables' value.
When I try passing string as parameters then the program couldn't compare the value right.
However when I add two same variables this code get me a right result.
Just as the picture shows.

You passed it a const char * pointer to compare and that will compare the pointer addresses, not the contents with '>'. As these are from different objects/strings, you have no way to know which will be first or last in memory, and it may vary from compile to compile, or even potentially run to run.
As you had the std::string local variable, I assume you intended to pass that, which does have comparison operators to compare the contents. If you want to pass a string literal as an std::string to such a template function, you must do it explicitly, such as:
Max<std::string>("a", "b"); // K is std::string, so both parameters will use the implicit constructor
Max(std::string("a"), std::string("b")); // Explicitly construct strings
If you do want Max to work with char pointers, you might overload or specialise it to use say strcmp, which does compare the contents.
template<class T> T Max(T x, T y)
{
return x > y ? x : y;
}
template<> const char* Max(const char *x, const char *y)
{
return strcmp(x, y) > 0 ? x : y;
}
template<> char* Max(char *x, char *y)
{
return strcmp(x, y) > 0 ? x : y;
}

Related

Frama-C - Get function input value through command line

Analysing the code below on GUI, it is possible check the input values of the function div0.
int div0(int x, int y)
{
return (x/y);
}
int main()
{
int res;
int a = 4;
int b = 2;
res = div0(a,b);
return 0;
}
Is it possible get this value through command line?
The simplest approach in your case is to insert calls to Frama_C_show_each, which is a special Frama-C builtin function that prints the internal Eva state for the given expressions, each time the interpreter passes through the program point. For instance:
int div0(int x, int y)
{
Frama_C_show_each_div0(x, y);
return (x/y);
}
Running frama-c -eva on the modified program will print:
[eva] file.c:3: Frama_C_show_each_div0: {4}, {2}
You can choose the suffix after Frama_C_show_each for each line you want. For instance, if you prefer to print each variable separately:
int div0(int x, int y)
{
Frama_C_show_each_x(x);
Frama_C_show_each_y(y);
return (x/y);
}
Will print instead:
[eva] file.c:3: Frama_C_show_each_x: {4}
[eva] file.c:4: Frama_C_show_each_y: {2}
For a more complex situation, or to avoid modifying the source code, other alternatives are possible, but they may require writing some OCaml code, either to modify Eva directly, or to add e.g. a new abstract domain which will print the expressions. But it's overkill for simple cases.
By the way, if you want your code to still compile normally, simply protect the call to Frama_C_show_each with #ifdef __FRAMAC__ guards:
int div0(int x, int y)
{
#ifdef __FRAMAC__
Frama_C_show_each_div0(x, y);
#endif
return (x/y);
}

How can I create an std::array of char array?

I was trying to create a std::array of char array so that I could declare it static constexpr.
eg:
#include <array>
int main(){
static constexpr char A[] = "abc";
static constexpr char B[] = "def";
static constexpr std::array<char[], 3> tmp{A, B};
}
When I do this I get error message " too many initializers for"
By output of your compiler I could surmise that you have a non-standard extension active. Stricly ISO-wise use of char[] as parameter of template is not legal,. Some compilers would treat that as char[0].
what your array meant to store? way you're trying to do it would store adresses of array to char (and only way to do so would be replace char[] by by const char* in template parameters. std::array is trivial class which stores data statically so you cannot implement array with variable length of strings that way.
Either 1) abolish constexpr and use std::string 2) use const char* 3) worst case (which sometimes is the best) - use fixed array length or "naked" 2-dimensional array with aggregate initializer list.
You may use:
static constexpr std::array<char[4], 2> tmp {{{ A[0], A[1], A[2], A[3] },
{ B[0], B[1], B[2], B[3] }}};
or
static constexpr std::array<char[4], 2> tmp { "abc", "def" };
From http://en.cppreference.com/w/cpp/container/array:
When initializing an object of array type, the initializer must be either a string literal (optionally enclosed in braces) or be a brace-enclosed list of initialized for array members.
Thus you cannot initialize an array (member of std::array of char[4]) by an object of another array.
With C++20 std::to_array can be used.
static constexpr char A[] = "abc";
static constexpr char B[] = "def";
static constexpr auto tmp = std::to_array({A, B});

std::array in template specialization

I want to write a function that take n int as a coordinate of array with the max value for each coordinate. This function linearizes these parameters to target a specific index.
int my_func(int x, int y, int XMAX, int YMAX){
return x + y*XMAX;
}
Here is a 2D example, but I can make something generic thanks to variadic template quite easily.
However, I am stucked when I want to make the same function that does not take the max value for each coordinate in parameters.
Something like that :
template<int XMAX, int YMAX>
int my_func(int x, int y){
return x + y*XMAX;
}
Here it works in 2D, but I want to generalize that from 1 to N dimensions and I don't know how I could achieve that.
I was thinking to pass an int N which is the number of dimension and an std::array<N, int>::iterator which is an iterator on the std::array containing the actual max value, but it does not compile.
Here is the code:
template <int N, std::array<size_t, N>::iterator it>
void foo(){...}
It says ’std::array<long unsigned int, N>::iterator’ is not a type.
If i just pass the std::array, I get the following error : ’struct std::array<long unsigned int, N>’ is not a valid type for a template non-type parameter
Does someone have an idea on how to solve such a problem ? I am using C++ 11 (G++ 5.4.0).
First of all, I suppose you did a little mistake in your function, because if you need to linearize the accessing of array you need to multuply y by XMAX
int my_func(int x, int y, int XMAX, int YMAX){
return x + y*XMAX;
}
because each row is composed of XMAX items. For answer to your question I used a template parameter pack
template <int N>
int my_func(int x)
{
assert(x < N);
return x;
}
template <int N, int... Ns, typename ARG, typename... ARGS>
ARG my_func (ARG x, ARGS... args)
{
assert(x < N);
return x + N*my_func<Ns...>(args...);
}
int main()
{
int a = 1;
int b = 2;
int c = my_func<10, 3>(a, b);
}
The fist function is the base for the recursion, the second function use two parameter packs but also 2 explicit template parameter to make the recursion possible.

Variadic Template Recursion

I am trying to use recursion to solve this problem where if i call
decimal<0,0,1>();
i should get the decimal number (4 in this case).
I am trying to use recursion with variadic templates but cannot get it to work.
Here's my code;
template<>
int decimal(){
return 0;
}
template<bool a,bool...pack>
int decimal(){
cout<<a<<"called"<<endl;
return a*2 + decimal<pack...>();
};
int main(int argc, char *argv[]){
cout<<decimal<0,0,1>()<<endl;
return 0;
}
What would be the best way to solve this?
template<typename = void>
int decimal(){
return 0;
}
template<bool a,bool...pack>
int decimal(){
cout<<a<<"called"<<endl;
return a + 2*decimal<pack...>();
};
The problem was with the recursive case, where it expects to be able to call decltype<>(). That is what I have defined in the first overload above. You can essentially ignore the typename=void, the is just necessary to allow the first one to compile.
A possible solution can be the use of a constexpr function (so you can use it's values it's value run-time, when appropriate) where the values are argument of the function.
Something like
#include <iostream>
constexpr int decimal ()
{ return 0; }
template <typename T, typename ... packT>
constexpr int decimal (T const & a, packT ... pack)
{ return a*2 + decimal(pack...); }
int main(int argc, char *argv[])
{
constexpr int val { decimal(0, 0, 1) };
static_assert( val == 2, "!");
std::cout << val << std::endl;
return 0;
}
But I obtain 2, not 4.
Are you sure that your code should return 4?
-- EDIT --
As pointed by aschepler, my example decimal() template function return "eturns twice the sum of its arguments, which is not" what do you want.
Well, with 0, 1, true and false you obtain the same; with other number, you obtain different results.
But you can modify decimal() as follows
template <typename ... packT>
constexpr int decimal (bool a, packT ... pack)
{ return a*2 + decimal(pack...); }
to avoid this problem.
This is a C++14 solution. It is mostly C++11, except for std::integral_sequence nad std::index_sequence, both of which are relatively easy to implement in C++11.
template<bool...bs>
using bools = std::integer_sequence<bool, bs...>;
template<std::uint64_t x>
using uint64 = std::integral_constant< std::uint64_t, x >;
template<std::size_t N>
constexpr uint64< ((std::uint64_t)1) << (std::uint64_t)N > bit{};
template<std::uint64_t... xs>
struct or_bits : uint64<0> {};
template<std::int64_t x0, std::int64_t... xs>
struct or_bits<x0, xs...> : uint64<x0 | or_bits<xs...>{} > {};
template<bool...bs, std::size_t...Is>
constexpr
uint64<
or_bits<
uint64<
bs?bit<Is>:std::uint64_t(0)
>{}...
>{}
>
from_binary( bools<bs...> bits, std::index_sequence<Is...> ) {
(void)bits; // suppress warning
return {};
}
template<bool...bs>
constexpr
auto from_binary( bools<bs...> bits={} )
-> decltype( from_binary( bits, std::make_index_sequence<sizeof...(bs)>{} ) )
{ return {}; }
It generates the resulting value as a type with a constexpr conversion to scalar. This is slightly more powerful than a constexpr function in its "compile-time-ness".
It assumes that the first bit is the most significant bit in the list.
You can use from_binary<1,0,1>() or from_binary( bools<1,0,1>{} ).
Live example.
This particular style of type-based programming results in code that does all of its work in its signature. The bodies consist of return {};.

flatten vectors in a map

In C++, I have a map < int, vector < double > > or map < int, vector < some_Struct > >, I need to concatenate the vectors in this map and return the result.
The first version of the function is below:
#include <algorithm>
#include <vector>
vector < double >
flattenRecords(const map < int, vector < double > > & selected, int num_kept_reps)
{
vector < double > records;
int cnt = 0;
for (auto it = selected.begin(); it != selected.end(); ++it) {
records.insert(records.end(),
make_move_iterator(it->second.begin()),
make_move_iterator(it->second.end()));
cnt += 1;
if (cnt >= num_kept_reps)
break;
}
return records;
}
I know this is not what I intended to do, because I would like to keep the data in the map, and thus should not use make_move_iterator.
The codes can compile using g++ (GCC) 4.4.7 with the -std=c++0x flag.
So here is the question, I declare the map to be const, what happens when I try to use something like std::move to the vector in the map?
My second version is to use:
copy(it->second.begin(), it->second.end(), back_inserter(records));
I guess this does what I intend to do.
I am quite new to C++. The STL gives me a feeling of coding in python so I would like to try it.
Instead of using make_move_iterator(Iterator), just use Iterator if you would not like to move the elements. Eg:
records.insert(records.end(), it->second.begin(), it->second.end());
Your second version, as you guess, does indeed what you try to achieve.
Regarding your question about std::move on a const map, the std::move won't do anything in such a case. Since std::move is unconditional cast to rvalue, it'll cast the element to a const reference to an rvalue. Because it's const it'll match the lvalue ctor (copy ctor in this case), and not the move (copy) ctor.
Eg:
const std::string s1 = "Test";
const std::string s2 = std::move(s1);
This will invoke the copy constructor of std::string, not the move constructor. Hence, it'll do a copy, not a move.
This will do a move:
std::string s1 = "Test";
const std::string s2 = std::move(s1);
The s2 parameter in both examples does not have to be const. It makes no difference regarding the copy/move.
There is a 'pythonic' alternative, which you may like if you come from Python, using lambda and a "mapped-reduce" function
std::vector<double> merged = std::accumulate(selected.begin(),
selected.end(),
std::vector<double>(),
[](const std::vector<double>& a, std::vector<double>& b)
{
std::vector<double> result(a);
std::copy(b.begin(), b.end(), std::back_inserter(result));
return result;
});
);
std::move does not actually move data. It casts a reference to a r-value reference, which, if non-const, is a "movable" data type that move constructors can use. But it will never remove a const type qualifier, so using std::move on a const reference will not cast it to a movable type.

Resources