I might be completely off-track but ...
while using bunch of explicit conversions from ArrayView to Vector (which I don't want implicit for obvious silent dangerous allocations) such as :
class MyClass
{
void SetInts(ArrayView<int> _view)
{
ints = Vector<int>(_view);
}
Vector<int> ints;
};
I was wondering if such a syntax was planned for future release of C++ (as we already got the auto return which does something quite similar) :
class MyClass
{
void SetInts(ArrayView<int> _view)
{
ints = auto(_view);
}
Vector<int> ints;
};
var = auto(expression) would be a kind of explicit conversion shortcut.
If not, is there some reasons not to write such a thing that I haven't spotted ?
I haven't heard of such proposals.
...But you don't need a new language feature to do that. Something like the following template should work just fine:
#include <utility>
template <typename T>
class auto_cast
{
T &&source;
public:
auto_cast(T &&source) : source(std::forward<T>(source)) {}
auto_cast(const auto_cast &) = delete;
auto_cast &operator=(const auto_cast &) = delete;
template <typename U, typename = decltype(U(std::forward<T>(source)))>
operator U()
{
return U(std::forward<T>(source));
}
};
template <typename T> auto_cast(T &&) -> auto_cast<T>;
Usage: ints = auto_cast(_view);
If not, is there some reasons not to write such a thing that I haven't spotted?
Yes, it's awkward at best and obsfucated at worst.
ints = auto(_view);
it looks like a function call, but using a keyword?
ints = Vector<int>(_view);
here we can see exactly whats happening, construction with possibly eluded copy assignment.
Related
My aim is to create my own analogue of std::basic_string but with some additional conditions. I want my AnyString<CharType, Traits> to be convertible from std::basic_string<CharType, AnyOtherTraits, AnyAlloc> but I want to disable this constructor for some CharType such that basic_string<CharType> does not exist (compile).
I tried to do something like that:
template<typename OtherTraits, typename Alloc, typename =
std::enable_if_t<!std::is_array_v<char_type> &&
std::is_trivial_v<char_type> &&
std::is_standard_layout_v<char_type>>>
AnyString(const std::basic_string<char_type, OtherTraits, Alloc>&);
And I have ColouredChar, which does not meet the conditions listed inside enable_if_t.
Now, when I'm trying to call the disabled constructor :
std::basic_string<ColouredChar> de("string"_purple);
ColouredString d(de);
I do not only get the compile errors from basic_string but also very strange one, telling me that completely different PRIVATE constructor constructor cannot convert its parameter from basic_string.
Is there any way to make these compile errors more readable? Or at least explain whether there's anything here to worry about.
Basic example for constructor restriction using concepts (not your traits)
#include <type_traits>
#include <string>
// declare your own concept
template<typename type_t>
concept my_concept = std::is_convertible_v<type_t, std::string>; // just a demo concept
class ColouredString
{
public:
// then you can limit your constructor to types satisfying that concept
ColouredString(const my_concept auto& /*arg*/)
{
}
~ColouredString() = default;
};
int main()
{
// ColouredString str{ 1 };
ColouredString str{ "hello world!" };
return 0;
}
just to point out, in addition to exist answer, you don't need to define a concept to use it in require-clause
class ColouredString{
public:
template<typename T>
requires (std::is_convertible_v<T, std::string>)
ColouredString(const T&){}
};
and there is already a std::convertable_to concept
class ColouredString{
public:
ColouredString(const std::convertible_to<std::string> auto&){}
};
fwiw, since you said
I want to disable this constructor for some CharType such that basic_string does not exist
your code fail with string constructor probably simply because you try to create one. it has nothing with ColouredString
std::basic_string<ColouredChar> de("string"_purple); // it already fail here
ColouredString d(de);
I'm trying to design a bool wrapper struct applying the safe bool idiom.
The classic implementation to solve this is pretty trivial: the skeleton could be something like this:
struct Bool final
{
Bool() = default;
Bool(bool value)
: _value{value}
{}
explicit operator bool() const {
return _value;
}
private:
bool _value{false};
};
The part I'm trying to improve is how Bool is constructed.
For example I want to avoid implicit narrowing by design:
Bool b1(45); // yields warnings, but it compiles
Bool b2{3}; // not ok by standard
I tried to hurt myself using templates, but without success.
How could I make it work?
You can achieve this by explicitly deleting all other constructors.
struct Bool final
{
template<class T>
Bool(T) = delete;
Bool(bool value);
};
Add, and explicitly delete a template constructor:
template <typename T>
Bool(T) = delete;
It matches anything other than actual bool better than other constructors, and will thus prevent implicit conversion.
If you just need:
A variable that is only "true" or "false" and cannot be implicitly converted to int/char/pointer then I would look at using an enum class:
enum class Bool {
False,
True,
};
I'm trying to design a bool wrapper struct applying the safe bool idiom.
Don't.
The safe bool idiom is only relevant in C++03 and earlier - where if you express that your type is "truthy" by doing something like:
struct A {
operator bool() const;
};
you'd run into all sorts of issues like:
A{} + 4; // ok?!
A{} < 0; // ok?!
A{} == B{}; // ok if B also has operator bool??!
So the safe bool idiom was a solution to this accidental implicit conversion problem, using function pointers (of course, function pointers!).
In C++11, we have a way better solution:
struct A {
explicit operator bool() const;
};
which does exactly what we want. In fact, it was literally designed to solve this problem. And while the safe bool idiom is fairly complicated scaffolding, explicit operator bool is super straightforward to use and just does the Right Thing. You don't need a wrapper for it - it's actually harder to use your wrapper than to write the explicit operator bool directly.
Moreover, your wrapper imposes on the user (a) non-derivability because you made Bool final and (b) an extra bool member, that you have to keep in sync, so it introduces rather than solves problems. Consider how much more work it would be for you to implement:
template <class T>
struct my_unique_ptr : Bool { ... };
vs
template <class T>
struct my_unique_ptr {
T* ptr;
explicit operator bool() const { return ptr; }
};
I would like to have a std::string like class (say, string_n) such that objects of string_n cannot be more than N chars long.
N may be specified at compile time. An attempt to create string_n of larger length may assert or throw an exception.
One option is something like following but it would miss all the nice member functions offered by std::string.
template <size_t N>
class string_n {
char char_[N + 1];
};
Another option is to roll out a new class like the following.
template <size_t N>
class string_n {
public:
// constructor and assignment operators with length check
~string_n() = default;
// for readers
const string& get() const;
private:
std::string string_;
};
This would require a lot of boilerplate code.
I have a feeling that there might be a better approach. What would you suggest?
This gets close:
template<size_t N, class CharT, class Traits = std::char_traits<CharT>>
struct basic_string_n:
std::array<CharT, N>,
std::experimental::basic_string_view<CharT, Traits>
{
using storage = std::array<CharT, N>;
using access = std::experimental::basic_string_view<CharT, Traits>;
using storage::operator[];
using storage::data;
using access::size;
basic_string_n(basic_string_n const& o):
storage(o),
access(regen(*this))
{}
basic_string_n& operator=(basic_string_n const& o)
{
*this = (storage const&)o;
*this = regen(*this);
return *this;
}
void remove_prefix(std::size_t n) = delete;
void remove_suffix(std::size_t n) = delete;
void swap( basic_string_n& other ) {
using std::swap;
swap( (storage&)*this, (storage&)other );
*this = regen(*this);
other = regen(other);
}
private:
friend access regen(storage& self) {
return {self.data(), CharT::length(self.data())};
}
};
here we mix an array of characters with a std::experimental::basic_string_view. What is missing are operations to add or remove characters.
that's my poor approach based on other answers, did it a couple weeks ago:
https://gist.github.com/digitalist/a48a9a7edd5a105bafe5
uses a custom allocators, there are links to stackoverflow answers in the source.
I'm still learning C++ and hints are very welcome, I'll need to use this gist later
I am implementing a type T. Although this is not a requirement, users of this type may benefit from move semantic, that is T(T&&) and T& operator=(T&&).
Since T contains std::function's as member data, I cannot implement move semantic with the noexcept guarantees, which would make T less useful for the user.
Also, for the above reason, my implementation cannot be as simple as: T(&&) noexcept = default and T& operator=(T&&) noexcept = default
The alternative would be to either offer the user the non-noexcept versions: T(&&) = default and T& operator=(T&&) = default; or implement my user defined noexcept move semantic in terms of std::function::swap() (which is guaranteed to be noexcept). In the latter case, I would unfortunately have to take care of all the other member data other than std::function's (ugly!).
So, there are three options:
disable move semantic at all
implement T(&&) = default and T& operator=(T&&) = default
implement my own T(&&) noexcept {/* lot of code */} and T& operator=(T&&) noexcept {/* lot of code */}
I know the question is rather subjective, but What would you opt for?
Assuming you really want the noexcept move, you can reduce the amount of boilerplate for option #3 by either:
grouping the default-noexcept-moveable members into a nested struct member or private base class, and write a move-ctor which simply moves that (one line for all of them), and then swaps the std::functions, or
writing a SwapMove template wrapper for storing a function in. It just needs to implement the move ctor and assignment operator using swap, and default everything else. OK, you'll also need to either expose the function member or forward the function call operator.
Why don't you try to put all your functions in a std::function inside a std::vector then swap the vector ?
vector has noexcept move constructor.
EDIT:
To fully expand the needed concepts, i cannot reply in comments.
For your situation (different function signatures) you will require type erasure and some dynamic casts.
Here's some code that uses all the stated concepts in a coment (vector and enum and others ).
Now you can keep a vector of your lambdas , regardless of signature.
class LambdaContainer
{
public:
struct GenericContainer {
virtual ~GenericContainer(){}
};
template <typename T>
struct SpecializedContainer : GenericContainer
{
SpecializedContainer(const T& t) : lambda(t){}
virtual ~SpecializedContainer(){}
T lambda;
};
private:
std::shared_ptr<GenericContainer> myLambda;
public:
template <typename T>
LambdaContainer(const T& aLambda) : myLambda(new SpecializedContainer<T>(aLambda)){}
std::shared_ptr<GenericContainer> getContainedLambda()
{
return myLambda;
}
};
enum eFunctions
{
FCT_INT=0,
FCT_FLOAT=1
};
...
int main()
{
int aa = 10;
float b = 3.0f;
std::function<void(int)> lambda1 = [aa](int arg)
{
printf("at this time b plus argument is %d\n ",aa+arg);
};
std::function<int (float, float )> lambda2 = [b] (float arg1, float arg2)
{ printf("calling the sum of floats %f , %f\n");
return (int)(arg1+arg2+b);};
std::vector<LambdaContainer> lambdaVector;
lambdaVector.push_back(LambdaContainer(lambda1));
lambdaVector.push_back(LambdaContainer(lambda2));
std::shared_ptr<LambdaContainer::GenericContainer> container = lambdaVector[FCT_INT].getContainedLambda();
LambdaContainer::SpecializedContainer<std::function<void(int)> >* ptr =
dynamic_cast<LambdaContainer::SpecializedContainer<std::function<void(int)> >*> (container.get());
if (ptr!=NULL)
{
std::function<void(int)> extractedLambda = ptr->lambda;
extractedLambda(5);
}
std::shared_ptr<LambdaContainer::GenericContainer> container2 = lambdaVector[FCT_FLOAT].getContainedLambda();
LambdaContainer::SpecializedContainer<std::function<int(float,float)> >* ptr2 =
dynamic_cast<LambdaContainer::SpecializedContainer<std::function<int(float,float)> >*> (container2.get());
if (ptr2!=NULL)
{
std::function<int(float,float)> extractedLambda = ptr2->lambda;
printf("the sum is %d\n",extractedLambda(3.0f,2.0f));
}
}
boost::optional<T> (1.51) provides a way of constructing objects that is very dangerous for my users and that I'd like to prevent. Let's say I have my own integer class and I want to pass an optional such integer and store it in some class:
class myint {
public:
int m_a;
myint (int r_a) : m_a(r_a) {
}
};
struct myclass {
boost::optional<myint> content;
myclass (const boost::optional<myint>& arg) : content(arg) {
}
};
and now, here's how users would use the class:
myclass(myint(13)); //correct use
myclass(boost::none); //correct use
myclass(myint(0)); //correct use
myclass(0); //INCORRECT use, this easy typo
//equates boost::none which
//is not what the user meant
I'd like to understand what is going on here and prevent this behaviour.
Interestingly,
myclass(1); //does not compile
boost::none is totally a valid value for my field, but having a boost::none sneak-up when the user is trying to type in a 0 is horrendously misleading and dangerous.
The intent might be a bit hidden since I'm not really rolling out a myint class and I don't really have a class myclass that serves little to no purpose. Anyways I need to send 10 or so optional ints to a function and deduping wouldn't work. (you can imagine I asked you for your age, your height and your wealth and that there's three special buttons to check if you don't want to answer a question)
I've posted an answer that seems to work below (built from Mooing's Duck & Ilonesmiz suggestion, but lighter). I'm happy to hear comments about it, though.
Do not let the constructor take a boost::optional I would do something like this instead.
struct myclass {
boost::optional<myint> content;
myclass () = default;
explicit myclass(const myint& int_):content(int_){}
};
However when I am thinking about it I am not completely clear on what you are trying to achieve and what you want to avoid happening. What is the purpose of the optional member?
This is uglier than I like, but it seems to address your concerns. It works by forwarding the argument given to myclass perfectly to a pair of functions that take either an int or a boost::none_t, bypassing the implicit user-defined constructor. This works because 0 matches int better than boost::none_t, and an implicit user-defined constructor is the worst match.
class myint {
public:
int m_a;
myint (int r_a) : m_a(r_a) {}
};
boost::optional<myint> myintctor(int arg) {return myint(arg);}
boost::optional<myint> myintctor(boost::none_t arg) {return arg;}
struct myclass {
boost::optional<myint> content0;
boost::optional<myint> content1;
boost::optional<myint> content2;
template<class T0, class T1, class T2>
myclass(const T0& a0, const T1& a1, const T2& a2)
:content0(myintctor(a0)), content1(myintctor(a1)), content2(myintctor(a2))
{}
};
Proof of concept. Modern compilers ought to be smart enough to elide the copy, but that shouldn't matter for an int.
I guess the problem is only meaningful for optional int. One solution could be to provide two constructors:
myclass() : content(boost::none) {}
myclass(myint input) : content(input) {}
It's true that you lose a bit the advantage of boost::optional...
This code (Inspired from Ilonesmiz) seems to do the job fine and is a bit lighter than the approach from Mooing Duck but still uses the magic templating trick.
struct myprotectedclass {
boost::optional<myint> content;
template <class T>
myprotectedclass(const T& a) :content(boost::optional<myint>(a)) {}
};
Here is the proof.
When C++ sees the 0, it thinks "hmm, this is probably an int, but it might be a pointer to something!" (only for 0, no other numbers) But if you pass that 0 to a function, it must decide on a type, and so it picks the default of int. Whereas, in the original, a 0 was passed to a function expecting a myint or a pointer (boost::none_t is a pointer). 0 isn't a myint, but it can be a pointer, so it was picking that one.