Tried to make universal solution for my template function GenerateDictionary(...) to accept both rvalue and lvalue as generator.
This works, but I'm not sure that this is a correct way of making perfect forwarding here. I'll be happy to see any suggestions how to improve this example.
std::string GenerateWord(std::mt19937& generator, int max_length) {
const int length =
std::uniform_int_distribution(1, max_length)(generator);
std::string word;
word.reserve(length);
for (int i = 0; i < length; ++i) {
word.push_back(
std::uniform_int_distribution<int>('a', 'z')(generator));
}
return word;
}
template <template <typename> typename Container, typename Rand>
Container<std::string> GenerateDictionary(Rand&& generator, int word_count,
int max_length) {
std::vector<std::string> words;
words.reserve(word_count);
for (int i = 0; i < word_count; ++i) {
words.push_back(
GenerateWord(std::forward<Rand&>(generator), max_length));
}
return Container(words.begin(), words.end());
}
I understand that perfect forwarding may be pointless here, but anyway I want to know the safe way to use it here. Tried this to avoid the function to accept anything except mt19937.
template <typename T>
class CanReserve {
struct Small {
char c;
};
struct Large {
char arr[2];
};
template <typename C>
static Small test(decltype(&C::reserve));
template <typename C>
static Large test(...);
public:
enum { value = sizeof(test<T>()) == sizeof(Small) };
};
template <typename Rand,
typename = std::enable_if<std::is_same_v<Rand, std::mt19937>>>
std::string GenerateWord(Rand&& generator, int max_length) {
const int length =
std::uniform_int_distribution(1, max_length)(generator);
std::string word;
word.reserve(length);
auto letter_distr = std::uniform_int_distribution<int>('a', 'z');
for (int i = 0; i < length; ++i) {
word.push_back(letter_distr(generator));
}
return word;
}
template <template <typename...> typename Container, typename Rand,
typename = std::enable_if<std::is_same_v<Rand, std::mt19937>>>
Container<std::string> GenerateDictionary(Rand&& generator, int word_count,
int max_length) {
Container<std::string> words;
if constexpr (CanReserve<Container<std::string>>::value) {
words.reserve(word_count);
}
for (int i = 0; i < word_count; ++i) {
words.push_back(
GenerateWord(std::forward<Rand>(generator), max_length));
}
return words;
}
Related
This question already has answers here:
How to avoid decay with template parameter deduction
(2 answers)
Closed 3 years ago.
I have this code:
template <typename T, ::std::size_t size>
using ary_t = T[size];
template <typename T, ::std::size_t size>
constexpr int call_me(ary_t<T const, size> &a)
{
int total = 10;
for (::std::size_t i = 0; i < size; ++i) {
total += a[i];
}
return total;
}
template <typename T>
constexpr int call_me(T const *a)
{
int total = 0;
for (int i = 0; a[i]; ++i) {
total += a[i];
}
return total;
}
#if 0
int t1()
{
return call_me("a test");
}
#endif
int t2()
{
char const * const s = "a test";
return call_me(s);
}
and it works, but when remove the #if 0 section around t1 it fails to compile because of an ambiguity in which template to use. Is there any way to force the array version of call_me to be used preferentially?
I've tried a number of different tricks to make this work. I've tried adding , int... to the template argument list for the pointer version. I've tried removing the const. I've tried both. I've even tried making the pointer version into a C-style varargs function (aka int call_me(T const *a, ...)). Nothing seems to work.
I'd be happy with an answer that requires what is currently believed will make it into C++2a.
There's an easy workaround:
template <typename T>
constexpr int call_me(T&& arg) {
if constexpr(std::is_pointer_v<std::remove_reference_t<T>>) {
return call_me_pointer(arg);
} else {
return call_me_array(arg);
}
}
If you accept to add a level of indirection, you can add an unused parameter to give the precedence to the array version.
I mean
template <typename T, std::size_t size>
constexpr int call_me_helper (ary_t<T, size> &a, int)
{
int total = 10;
for (std::size_t i = 0; i < size; ++i) {
total += a[i];
}
return total;
}
template <typename T>
constexpr int call_me_helper (T const * a, long)
{
int total = 0;
for (int i = 0; a[i]; ++i) {
total += a[i];
}
return total;
}
template <typename T>
constexpr int call_me (T const & a)
{ return call_me_helper(a, 0); }
I suggest you achieve the same effect by using a span:
What is a "span" and when should I use one?
You just replace the array reference with a fixed-size span:
#include <cstddef>
#include <gsl/span>
template <typename T, std::size_t size>
constexpr int call_me(gsl::span<T const, size> a)
{
int total = 10;
for (std::size_t i = 0; i < size; ++i) {
total += a[i];
}
return total;
}
And there's no ambiguity. What's even nicer is that now you can use standard-library algorithms on containers:
#include <numeric>
template <typename T, std::size_t size>
constexpr int call_me(gsl::span<T const, size> a)
{
return std::accumulate(a.begin(), a.end(), 10);
}
Say I have
constexpr const std::uint8_t major = 1;
constexpr const std::uint8_t minor = 10;
constexpr const std::uint8_t bugfix = 0;
and I want
constexpr const char* version_string(){ ... }
to return the equivalent of "1.10.0" in this example, how would I do it?
I assume I'll need both of these, in constexpr:
integer to string conversion
string concatenation
The problem is purely academic, and I see little to no use to actually have it constexpr other than "it's possible". I just can't see how this would pan out. I'm willing to accept C++1y solutions that work on GCC 4.9 and Clang 3.4/3.5.
I believe I have found nearly what I seek on some Japanese blogs:
constexpr itoa
constexpr strcat
I will see what I can do with these, and perhaps answer this self-declared interesting question myself when I'm satisfied with the result.
Here's a little C++1y solution --- I think I LOVE C++1y.
#include <utility>
template<int N>
struct c_string
{
int length;
char str[N+1];
constexpr explicit c_string(int p_length)
: length(p_length), str{}
{}
};
template<int M>
constexpr auto make_c_string(char const (&str)[M])
{
c_string<M-1> ret{M-1};
for(int i = 0; i < M; ++i)
{
ret.str[i] = str[i];
}
return ret;
}
template<int N, int M>
constexpr auto join(c_string<N> const& x, c_string<M> const& y)
{
c_string<N+M> ret{x.length + y.length};
for(int i = 0; i < x.length; ++i)
{
ret.str[i] = x.str[i];
}
for(int i = 0; i < y.length; ++i)
{
ret.str[i+x.length] = y.str[i];
}
ret.str[N+M] = '\0';
return ret;
}
template<int N, int M>
constexpr auto operator+(c_string<N> const& x, c_string<M> const& y)
{
return join(x, y);
}
template<class T>
constexpr void c_swap(T& x, T& y)
{
T tmp( std::move(x) );
x = std::move(y);
y = std::move(tmp);
}
// from http://en.cppreference.com/w/cpp/algorithm/reverse
template<class I>
constexpr void reverse(I beg, I end)
{
while(beg != end && beg != --end)
{
c_swap(*beg, *end);
++beg;
}
}
Now the constexpr itoa:
#include <limits>
template<class T>
constexpr auto c_abs(T x)
{
return x < T{0} ? -x : x;
}
template<class T>
constexpr auto ntoa(T n)
{
c_string< std::numeric_limits<T>::digits10 + 1 > ret{0};
int pos = 0;
T cn = n;
do
{
ret.str[pos] = '0' + c_abs(cn % 10);
++pos;
cn /= 10;
}while(cn != T{0});
if(n < T{0})
{
ret.str[pos] = '-';
++pos;
}
ret.str[pos] = '\0';
ret.length = pos;
reverse(ret.str, ret.str+ret.length);
return ret;
}
We can then simplify the usage:
#include <type_traits>
// not supported by the libstdc++ at coliru
//template<class T, class = std::enable_if_t< std::is_arithmetic<T>{} >>
template<class T, class = typename std::enable_if<std::is_arithmetic<T>{}>::type>
constexpr auto to_c_string(T p)
{
return ntoa(p);
}
template<int N>
constexpr auto to_c_string(char const (&str)[N])
{
return make_c_string(str);
}
template<class T, class U, class... TT>
constexpr auto to_c_string(T&& p0, U&& p1, TT&&... params)
{
return to_c_string(std::forward<T>(p0))
+ to_c_string(std::forward<U>(p1), std::forward<TT>(params)...);
}
And a usage example:
#include <iostream>
int main()
{
constexpr auto res = to_c_string(42," is the solution, or is it ",-21,"?");
std::cout << res.str;
}
Live example # coliru's clang++3.4
Here is a C++11 solution. It uses class templates with char... parameter pack to simulate strings:
#include <iostream>
#include <type_traits>
template <char... symbols>
struct String
{
static constexpr char value[] = {symbols...};
};
template <char... symbols>
constexpr char String<symbols...>::value[];
template <typename, typename>
struct Concat;
template <char... symbols1, char... symbols2>
struct Concat<String<symbols1...>, String<symbols2...>>
{
using type = String<symbols1..., symbols2...>;
};
template <typename...>
struct Concatenate;
template <typename S, typename... Strings>
struct Concatenate<S, Strings...>
{
using type = typename Concat<S, typename Concatenate<Strings...>::type>::type;
};
template <>
struct Concatenate<>
{
using type = String<>;
};
template <std::size_t N>
struct NumberToString
{
using type = typename Concat
<
typename std::conditional<(N >= 10), typename NumberToString<N / 10>::type, String<>>::type,
String<'0' + N % 10>
>::type;
};
template <>
struct NumberToString<0>
{
using type = String<'0'>;
};
constexpr const std::uint8_t major = 1;
constexpr const std::uint8_t minor = 10;
constexpr const std::uint8_t bugfix = 0;
using VersionString = Concatenate
<
NumberToString<major>::type,
String<'.'>,
NumberToString<minor>::type,
String<'.'>,
NumberToString<bugfix>::type
>::type;
constexpr const char* version_string = VersionString::value;
int main()
{
std::cout << version_string << std::endl;
}
See live example.
Here is my quick and dirty solution: http://coliru.stacked-crooked.com/a/43c9b365f6435991
It exploits the fact that a 'major.minor.fix' string will be quite short, so I just use a fixed-size array big enough to hold the string. The int-to-string function uses push_front to prepend characters to string, so the whole string grows from end of buffer.
#include <cstdint>
constexpr const std::uint8_t major = 1;
constexpr const std::uint8_t minor = 10;
constexpr const std::uint8_t bugfix = 0;
struct char_array {
constexpr char_array() : ofs{sizeof(value) - 1}, value{} {}
constexpr const char* c_str() const { return value + ofs; }
constexpr void push_front(char c) {
--ofs;
value[ofs] = c;
}
private:
int ofs;
char value[42]; // big enough to hold version string
};
constexpr char_array predend_int(char_array a, int x) {
do {
auto digit = x % 10;
x = x / 10;
a.push_front(digit + '0');
}
while (x);
return a;
}
constexpr auto version_string() {
char_array a;
a = predend_int(a, bugfix);
a.push_front('.');
a = predend_int(a, minor);
a.push_front('.');
a = predend_int(a, major);
return a;
}
#include <iostream>
int main() {
constexpr char_array ver = version_string();
std::cout << ver.c_str() << '\n';
}
Update:
It's probably better to make a dedicated class for version string generation, and put all the functions in it: http://coliru.stacked-crooked.com/a/5e5ee49121cf6205
Suppose, I have class with such definition:
template<unsigned int N>
class A { ... }
The question is how to iterate over this classes with N?
for(unsigned int i = 0; i < 10; ++i) {
A<i>().doStuff();
}
Maybe there is some new feature in C++ 11 or some cool using of contrexp .
And next question is: if it's possible - how to store such classes?
Update
I know that it works at compile time. Suppose, I have up to 10 such global classes, which differs only in N. For example:
A<1> first;
A<2> second;
A<42> third;
A<1034> fourth;
And suppose, I should call the one who's got N bigger than my value. If there is no chances to iterate, so I have to write long if-else structure.
void doAppropriateStuff(int value) {
if (value < 1) {
first.doStuff();
} else if (value < 2) {
second.doStuff();
} else if (value < 42) {
third.doStuff();
} else if (value < 1034) {
fourth.doStuff();
} else {
...
}
}
Hope, the problem became clearer.
As I googled that's impossible and I understand why. Only hopes on C++11 and SO community.
Thanks.
It's obviously impossible with a for loop, because that's ran at runtime and template arguments need to be compile time constants. Here's how you could do it.
These are utility classes for constructing a sequence of integers as a template argument pack:
template< std::size_t... Ns >
struct indices {
typedef indices< Ns..., sizeof...( Ns ) > next;
};
template< std::size_t N >
struct make_indices {
typedef typename make_indices< N - 1 >::type::next type;
};
template<>
struct make_indices< 0 > {
typedef indices<> type;
};
The function that does the work:
#include <initializer_list>
template<size_t... Is>
void foo(indices<Is...>)
{
auto list = { (A<Is>().doStuff(), 0)... };
}
And you call the function like this:
foo(make_indices<10>::type());
If you do not want to rely on integer_sequence that is c++14, this is a simpler solution :
#include <iostream>
template<unsigned int N>
struct A {
void dostuff() const { std::cout << N << " "; }
};
template < int N > void run();
template <> void run<-1>() {}
template < int N > void run() {
run<N-1>();
A<N>{}.dostuff();
}
int main() {
run<10>();
}
EDIT : about your question update, you can do that if you store the objects inside a tuple, see here :
#include <iostream>
#include <tuple>
template<unsigned int N>
struct A {
unsigned int getN() const { return N; }
void dostuff() const { std::cout << N << " "; }
};
auto globals = std::make_tuple( A<3>{}, A<7>{}, A<10>{}, A<200>{} );
template <int idx> void run( int v );
template <> void run<std::tuple_size<decltype(globals)>::value>( int ) {}
template <int idx = 0> void run( int v ) {
auto & a = std::get<idx>(globals);
if ( v < a.getN() ) {
a.dostuff();
} else {
run<idx+1>(v);
}
}
int main() {
for( int i = 0; i<20; ++i)
run( i );
}
You would use template specialization:
template <unsigned int N> struct ADoer
{
static void go() { A<N>().doStuff(); ADoer<N - 1>::go(); }
};
template <> struct ADoer<0>
{
static void go() { }
};
Is there a unique way to achieve a uniform call syntax for a convert function like the following for any kind of type? The function takes a string and converts it into the given TYPE (here int and MyMatrix<double>::Vector3 , call by reference of course!!)
int a;
std::string b = "asd";
stringToType::call(a,b);
MyMatrix<double>::Vector3 g; // Vector3 might be any type e.g Eigen::Matrix<double,3,1>
stringToType::call(g,b);
e.g:
template<typename T>
struct MyMatrix{
typedef Eigen::Matrix<T,3,1> Vector3;
};
I would like that the convert function converts types in the form of Eigen::Matrix<T,3,1> with T arbitary with the same function,
It should also support the basic types which have no template parameters (like the int)
You may want something like that:
#include <string>
#include <sstream>
namespace details
{
template <typename T>
struct stringToTypeImpl
{
void operator () (std::stringstream& ss, T& t) const
{
ss >> t;
}
};
// And some specializations
template <typename T, int W, int H>
struct stringToTypeImpl<Eigen::Matrix<T, W, H> >
{
void operator () (std::stringstream& ss, Eigen::Matrix<T, W, H>& t) const
{
for (int j = 0; j != H; ++j) {
for (int i = 0; i != W; ++i) {
stringToTypeImpl<T>()(ss, t(i, j)); //ss >> t(i, j);
}
}
}
}
// ...
}
template <typename T>
void stringToType(const std::string& s, T& t)
{
std::stringstream ss(s);
details::stringToTypeImpl<T>()(ss, t);
}
int main() {
std::string s = "42";
int i;
stringToType(s, i);
return 0;
}
I would like to define a simple template function which takes a runtime value and determines if it is a member of some set of possible values.
Usage:
int x; // <- pretend this came from elsewhere...
if (isoneof(x, {5,3,9,25}) ...
Something like:
template <typename T, size_t size>
bool isoneof(T value, T (&arr)[size])
{
for (size_t i = 0; i < size; ++i)
if (value == arr[i])
return true;
return false;
}
I assume that this is doomed to failure, as I don't see how one can create a static array inline.
I can use:
int kPossibilities[] = {5,3,9,25};
if (isoneodf(6, kPossibilities)) ...
With a minor change to isoneof:
template <typename T1, typename T2, size_t size>
bool isoneof(T1 value, const T2 (&arr)[size])
{
for (size_t i = 0; i < size; ++i)
if (value == arr[i])
return true;
return false;
}
Which also makes it a tad more flexible.
Does anyone have an improvement to offer? A better way to define a "set of static values inline"?
If you like such things, then you will be a very happy user of Boost.Assign.
Boost.Assign actually proves that such semantics are possible, however one look at the source of assign will convince you that you don't want to do that by yourself :)
You will be able to create something like this however:
if (isoneof(x, list_of(2)(3)(5)(7)(11)) { ...
... the downside being you'd have to use boost::array as the parameter instead of a built-in array (thanks, Manuel) -- however, that's a nice moment to actually start using them :>
It's possible in the next C++ standard.
Up till then, you can work around it by e.g. overloading operator, for a static object that starts a static array.
Note: this implementation is O(n^2) and may be optimized - it's just to get the idea.
using namespace std;
template< typename T, size_t N >
struct CHead {
T values[N];
template< typename T > CHead<T,N+1> operator,( T t ) {
CHead<T,N+1> newhead;
copy( values, values+N, newhead.values);
newhead.values[N]=t;
return newhead;
}
bool contains( T t ) const {
return find( values, values+N, t ) != values+N;
}
};
struct CHeadProto {
template< typename T >
CHead<T,1> operator,( T t ) {
CHead<T,1> h = {t};
return h;
}
} head;
int main()
{
assert( (head, 1,2,3,4).contains(1) );
return 0;
}
For the sake of completeness, I'll post a solution that uses Boost.MPL. The following works, but I think Kornel's solution is best.
#include <iostream>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector_c.hpp>
struct Contains
{
Contains(int value, bool& result) : value(value), result(result)
{
result = false;
}
template< typename T > void operator()(T x)
{
result = result || (x == value);
}
int value;
bool& result;
};
template <class IntList>
bool isoneof(int val)
{
namespace mpl = boost::mpl;
bool result;
mpl::for_each<IntList>(Contains(val, result));
return result;
}
int main()
{
namespace mpl = boost::mpl;
std::cout << isoneof< mpl::vector_c<int, 1,2,3,5,7,11> >(4) << "\n";
std::cout << isoneof< mpl::vector_c<int, 1,2,3,5,7,11> >(5) << "\n";
}
As you can see, the compile-time array is passed inline as a template argument to isoneof.
This one?
int ints[] = {2,3,5,7,11};
#define ARRAY_SIZE(Array) (sizeof(Array)/sizeof((Array)[0]))
#define INLIST(x,array) isoneof(x,array,ARRAY_SIZE(array))
ADDITION:
template <typename T>
bool isoneof(const T& x, T *array, int n)
{
for(int i=0; i<n; ++i)
if(x==array[i])
return true;
return false;
}
Using C++11, this would be written like this:
template <typename T>
bool isoneof(T value, std::initializer_list<T> arr)
{
using namespace std;
return any_of(begin(arr), end(arr), [&](const T& x) { return x == value; });
}
Just FYI - I solved my particular problem using vararg templates and initializer lists now that I have access to C++14:
template <typename T, typename U>
bool isoneof(T v, U v1) { return v == v1; }
template <typename T, typename U, typename... Args>
bool isoneof(T v, U v1, Args ... others) { return isoneof(v, v1) || isoneof(v, others...); }
template <typename T, typename U>
bool isoneof(T value, std::initializer_list<U> values)
{
for (const auto & e : values)
if (value == e)
return true;
return false;
}