variadic template method to create object - c++

I have a variadic template method inside a template class (of type T_) looking like this
template < typename T_ >
class MyContainer {
public:
...
template <typename ...A>
ulong add (A &&...args)
{
T_ t{args...};
// other stuff ...
vec.push_back(t);
// returning an ulong
}
}
So basically I'm trying to make this class adapt to whatever type T_ but since I can't know in advance which types its constructor requires, I use a variadic. I took inspiration from the emplace_back method from the stl library.
Nevertheless, I get a warning of narrowing conversion with integer types if I try to do something like this
MyContainer<SomeClassRequiringAnUlong> mc;
mc.add(2);
warning: narrowing conversion of ‘args#0’ from ‘int’ to ‘long unsigned int’ [-Wnarrowing]
So I was wondering if I can do anything about it. Is there any way to tell the method which parameters' type it is supposed to take according to the template parameter T_ (which is known when the object is created) ?

Is there any way to tell the method which parameters' type it is
supposed to take according to the template parameter T_ (which is
known when the object is created)?
In your case, you should use direct initialization(()) instead of list initialization({}) (to avoid unnecessary narrowing checks).
Consider the case where T is a vector<int>:
MyContainer<std::vector<int>> mc;
mc.add(3, 0);
What do you expect mc.add(3, 0) to do? In your add() function, T_ t{args...} will invoke vector<int>{3,0} and create a vector of size 2, which is obviously wrong. You should use T_ t(args...) to call the overload of vector(size_type count, const T& value) to construct a vector of size 3, just like emplace_back() does.
It is worth noting that due to P0960R3, T_ t(std::forward<Args>(args)...) can also perform aggregate initialization if T_ is aggregate.

In general, no. The rules of C++ explicitly allow implicit conversions to take place. The fact that the authors of C++ made some of those conversions potentially unsafe is another matter.
You could add std::is_constructible<T,A&&...> static_assert or SFINAE to the code to make the compiler errors less ugly if the user inputs wrong arguments, but it won't solve implicit conversions.
From design perspective, the code should not care about this, the purpose of emplace_XXX is to allow exactly the calls that are allowed for T{args...}.
Note: You most likely want to forward the arguments like T element{std::forward<A>(args)...}; and also move the element into the vector vec.push_back(std::move(t));.
That said, the code
T_ t{args...};
//...
vec.push_back(t);
is the exact opposite what emplace functions do, their purpose is to create the element in-place at its final destination. Not to copy or move it there.

You are looking in the wrong direction. It is not the template, but the user code that needs fix. To see the issue, first understand that 2 is of type signed int. So you are trying to construct an object with a signed int, while the constructor expects long unsigned int instead. A minimal repro of the issue can then be written as below.
class SomeClassRequiringAnUlong {
public:
SomeClassRequiringAnUlong(unsigned long) {}
};
int main() {
int v = 2;
SomeClassRequiringAnUlong obj{v};
}
The warning simply states that this narrowing conversion from signed int to long unsigned int is potentially risky and may catch you off guard. E.g.,
int v = -1;
SomeClassRequiringAnUlong obj{v};
still compiles and runs, but the result may not be what you want. Now you see that the issue lies in the user code. I see two ways to fix. 1) Use the type the constructor expects from the very beginning. In your case, that would be changing mc.add(2) to mc.add(2ul). 2ul is of type long unsigned int. 2) Make the type conversion explicit to inform the compiler that the narrowing conversion is by design and it is fine. That would be changing mc.add(2) to mc.add(static_cast<long unsigned int>(2)).
Note that there are issues in your template (though not quite related to the warning) as other answers have noted. But they are irrelevant to the specific question you asked. So I do not further elaborate on them.

Related

Advantages of static_cast over explicit instantiation/construction?

Considering the following function template func declared within MyClass class template:
template < T >
class MyClass {
public:
MyClass() = default;
// ...
template < typename oT >
oT func() {
return static_cast< oT >(_m); // alternative, return oT(_m);
}
// ...
protected:
T _m;
};
Is there any advantage in calling static_cast< oT >(_m) over explicit instantiation i.e. oT(_m)?
oT(_m) will allow many more conversions than is probably intended. If static_cast<oT>(_m) wouldn't be possible, then oT(_m) will also try a const_cast, static_cast followed by const_cast, reinterpret_cast and reinterpret_cast followed by const_cast.
For example if T is const int* and oT is double*, then oT(_m) will succeed, while static_cast<oT>(_m) will fail. But using the result from oT(_m) as if it was a pointer to a double will result in undefined behavior.
If T and oT are pointers to classes that is maybe even more dangerous, since oT(_m) will always compile, whether or not there is an inheritance relation between the two classes.
Even static_cast allows for some conversions that may not be intended. For example it can downcast pointers to classes.
Another alternative is simply return _m;. This is weaker than both variants above. It will only allow for copy-initialization. However that might be too weak depending on your use case. For example it will not use explicit constructors and conversion functions. On the other hand before C++17 it doesn't require oT to be move-constructible, which the first two variants do require before C++17.
So you will need to decide what casts are supposed to be allowed and which ones are supposed to fail.
However, nothing prevents a user from calling func<T>() to obtain the original type anyway and the user can then simply cast it however they like, so I am not sure what is gained here over a simple getter.
Even more so, the user can in either case call func<T&>() and will get a reference to the member, thereby making the protected somewhat pointless. Maybe the allowed types T need to be constrained via SFINAE/requires-clause.

Best viable overloaded function between std::reference_wrapper<const T> and T

Recently, I've decided to write a class storing a variant with reference_wrapper<const vector> and vector for having a choice either to own the value or having only a reference of it. That is, std::variant<vector<string>, reference_wrapper<const vector<string>>>.
The interesting part is what the variant stores depending on initialization.
I did a small investigation, and it turned out, that in all cases vector<string> type wins, except for the case when passing via std::cref. The same applies to functions (somewhat expected, because constructors are similar to functions in this way)
void f(vector<string>); // #1
void f(reference_wrapper<const vector<string>>); // #2
vector<string> data;
const vector<string>& get_data();
f(data); // #1
f(std::cref(data)) // #2
f(get_data()); // #1
f(std::cref(get_data())) // #2
The question is why the vector<string> has the priority here. I looked at Best viable function section here , but it didn't make much sense. It seems, that
4) or, if not that, F1 is a non-template function while F2 is a template specialization
part chooses vector<string> over reference_wrapper<vector<string>> (because reference_wrapper constructor is templated), but I'm not sure, because I can't fully understand if they are equal using the rule
1) There is at least one argument of F1 whose implicit conversion is better than the corresponding implicit conversion for that argument of F2
Can someone please describe all the implicit conversions applied in each case and show the true reason why one overload is preferred over another? To me, they are as follows:
f(data) = f(vector<string>&) -> (*exact match* implicit conversion) -> f(vector<string>)
f(data) = f(vector<string>&) -> (*conversion* implicit conversion) -> f(reference_wrapper<vector<string>>)
Did I miss something?
Another question, connected to this topic: Ranking of implicit conversion sequences section again,here leaves a question, is T(const T&) considered an Exact match (user-defined conversion of class type to the same class) or Conversion?
First, Although std::reference_wrapper is part of standard library it is treated as user-defined type.
For example an implicit conversion from std::vector & to const std::vector & is always preferred over an implicit conversion from std::vector& to std::reference_wrapper<vector>. That is because (as per standard) the former one is a standard conversion, but the later is a user-defined conversion. the first one is called standard conversion because it adds a const to your type but the second is treated as converting some type to totally different type.
check this code and see cppreference.com.
Second, I'm trying to guess some good alternative. I see you want either to store a reference to vector OR move/(copy as cheap as possible) or (you could say directly initialize) the data inside your class if it is not already stored (safely) in some variable. Maybe you could consider using move semantics. you can play with code here
using TVar = std::variant<reference_wrapper<const vector<string>>, vector<string>>;
class Config {
private:
TVar data;
public:
const vector<string>& get_data() const{
if (data.index() == 1)
return get<1>(data);
else return get<0>(data);
}
Config(const vector<string>& it):data(cref(it)){}
Config(vector<string>&& it):data(move(it)){}
};
Here we have two functions.
One that takes reference to "stored value" (more precisely lvalue). wrapping it in cref so that it causes the reference_wrapper alternative in the variant to be the best overload.
The other does the magic. it is the reference to values that are either written directly (aka pvalues) and values that use the magic std::move function (aka xvalues). if you have never seen this, please reference this respectable Q&A What is move semantics?
catch(...) :), this is it. also notice, you don't need the std::monostate as this is only needed for making the variant default constructible (with no arguments). you can make your class default constructible like this.
Config(vector<string>&& it = {}):data(move(it)){}
There is absolutely no reason to store reference_wrapper whatsoever. Just use a pointer like any sane programmer. reference_wrapper is used to properly trigger std::invoke and associated classes/functions like thread and bind.

User-defined conversions aren't applied to variadic function arguments? Why not?

I have a class that mainly wraps a std::variant with some minor additional functionality/meta-data.
For simplicity of use, I wanted to provide a user-defined conversion of this wrapper class to the underlying variant type, so functions like std::holds_alternative could be called directly on it.
What I've uncovered leaves me very confused about whether and when user-defined conversions will be applied. Here is simplified code.
#include <iostream>
#include <variant>
struct MyClass
{
// "MyClass" is implicitly convertible to a variant<bool,int>
operator std::variant <bool, int> ()
{
return std::variant<bool,int>(5);
}
};
void thisFunctionTakesOneSpecificVariantType (std::variant<bool,int> v)
{
std::cout << v.index();
}
template <class... types>
void thisFunctionTakesAnyVariantType (std::variant<types...> v)
{
std::cout << v.index();
}
int main ()
{
MyClass mc;
// 1. This compiles and runs as expected,
// proving the user-defined conversion (MyClass -> variant<int,bool>) exists and works "sometimes"
thisFunctionTakesOneSpecificVariantType (mc);
// 2. This compiles and runs as expected,
// proving "thisFunctionTakesAnyVariantType" is well defined
thisFunctionTakesAnyVariantType (std::variant <bool, int> (5));
// 3. But, combining 1 & 2, this fails to compile:
/* fails */ thisFunctionTakesAnyVariantType (mc); // error: no matching function for call to 'thisFunctionTakesAnyVariantType'
// 4. This is what i really want to do, and it also fails to compile
/* fails */ std::holds_alternative<int>(mc); // error: no matching function for call to 'holds_alternative'
// 5. An explicit conversion works for 3 and 4, but why not an implicit conversion?
// After all, the implicit conversion worked in #1
thisFunctionTakesAnyVariantType ( static_cast<std::variant <bool, int>> (mc) );
return EXIT_SUCCESS;
}
Why don't use cases 3 and 4 compile, while 1, 2, and 5 do?
In the error messages, it provides this note:
note: candidate template ignored: could not match 'variant<type-parameter-0-1...>' against 'MyClass'
inline constexpr bool holds_alternative(const variant<_Types...>& __v)
Why don't use cases 3 compile
Because implicit conversions are not considered in template argument deduction:
Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.
The conversion from MyClass to std::variant <bool, int> won't be considered then type deduction fails. As #5 showed you can apply explicit conversion before passing to thisFunctionTakesAnyVariantType.
Why don't use cases 4 compile
Same reason as #3. Note that even you specify some template arguments for the parameter pack template argument deduction still tries to deduce the following template arguments from the function argument. You can use exclude the function parameter from the deduction as
template <class... types>
void thisFunctionTakesAnyVariantType (std::type_identity_t<std::variant<types...>> v)
then you can call it as
thisFunctionTakesAnyVariantType<bool, int>(mc);
But note that this will make all the template argument deduction invalid (and #2 and 5 would fail), so it might be a bad idea.
BTW: std::type_identity is supported since C++20 even it's easy to implement one.
That's how the rules are laid out. Someone else with more knowledge then me might come and give you the exact rules at play here (template substitution and conversions considered), but at the end of the day it is what it is and you cannot change that.
In order for the conversion to be considered your class needs to inherit from std::variant<int, bool>. All of your examples will compile. I am however reluctant to recommend this approach as indeed composition seems the right design here.
What I would do is provide a conversion method. You lose the implicit aspect of it, but that maybe it's not such a bad idea, at least considering the alternative.
struct MyClass
{
std::variant<bool, int> to_var() const
{
return {5};
}
}
thisFunctionTakesAnyVariantType (mc.to_var());
std::holds_alternative<int>(mc.to_var());
You could leave the conversion operator for those situation where it works but consider if it doesn't just add confusion.

Emulating explicit cast in C++03

I'm working on a legacy library that needs to be backwards compatible with C++03, but is also forward compatible to take advantage of C++11 features like move semantics and explicit casting.
So, is it possible to emulate explicit casting in C++03? I know obviously about the explicit bool (or "safe" bool) idiom - but that's only for casting to a boolean type. Is it possible to emulate a general explicit cast operator in C++03?
I checked around, and found a discussion about this in a book called "Imperfect C++ : Practical Solutions for Real-Life Programming".
In this book, they discuss some ideas about emulating an explicit cast in C++03 (the book was written before C++11). Ultimately, they recommend creating an explicit_cast<T> template. However, I don't like that solution because I want users to simply be able to use static_cast<T>, which works fine in C++11.
So, another solution was to force the compiler to do two conversions, which will disallow implicit conversions. An example of that would be something like:
class int_cast
{
public:
int_cast(const int& v) : m_value(v)
{ }
operator int() const
{
return m_value;
}
private:
int m_value;
};
struct Foo
{
Foo()
{
x = 10;
}
operator int_cast() const
{
return int_cast(x);
}
int x;
};
Here, a Foo should be explicitly convertible to int, but not implicitly. (This code is lifted almost verbatim from Imperfect C++, except in their example they are converting a custom Time object to a std::tm.
However, this doesn't actually work, at least not using GCC 4.7.2:
Foo f;
int x = static_cast<int>(f);
This results in :
test3.cpp: In function ‘int main()’:
test3.cpp:44:28: error: invalid static_cast from type ‘Foo’ to type ‘int’
So I guess "Imperfect C++" is wrong here. The compiler wasn't able to convert a Foo to an int, even with an explicit cast. (Maybe this worked on older compilers?) So, is there anyway to emulate this in C++03 (without using a custom cast operator)?
"Imperfect C++" is right, because it uses a custom "keyword" - actually a function name masquerading as a keyword (not unlike eg.: Tribool's indeterminate). If you try to static_cast you crash against the limitation that the language can only accept conversion chains that involve up to one user-defined type, whereas you have two conversions - from "Foo" to "int_cast" and from there to int.
If you want specifically to be able to static_cast then you'll probably have to hack something with macros to supersede normal static_cast... and accept to live in Undefined Behaviour Land. My preferred choice is to actually work in the inverse direction: simply use explicit_cast and use a macro to redefine it as a static_cast invocation when in C++11 mode. I use explicit cast in my C++ backports toolkit and thus in all the C++ code I write, and I have found no important issues so far.

Why does boost::bind store arguments of the type passed in rather than of the type expected by the function?

I recently ran into a bug in my code when using boost::bind.
From the boost::bind docs:
The arguments that bind takes are copied and held internally by the returned function object.
I had assumed that the type of the copy that was being held was based on the signature of the function. However, it is actually based on the type of the value passed in.
In my case an implicit conversion was happening to convert the type used in the bind expression to the type received by the function. I was expecting this conversion to happen at the site of the bind, however it happens when the resulting function object is used.
In retrospect I should have been able to figure this out from the fact that using boost::bind gives errors when types are not compatible only at the call site, not the bind site.
My question is:
Why does boost::bind work this way?
It seems to give worse compiler error messages
It seems to be less efficient when implicit conversion happens and there are multiple calls to the functor
But given how well Boost is designed I'm guessing there is a reason. Was it behavior inherited from std::bind1st/bind2nd? Is there a subtle reason why this would be hard/impossible to implement? Something else entirely?
To test that second theory I wrote up a little code snippet that seems to work, but there may well be features of bind I haven't accounted for since it's just a fragment:
namespace b = boost;
template<class R, class B1, class A1>
b::_bi::bind_t<R, R (*) (B1), typename b::_bi::list_av_1<B1>::type>
mybind(R (*f) (B1), A1 a1)
{
typedef R (*F) (B1);
typedef typename b::_bi::list_av_1<B1>::type list_type;
return b::_bi::bind_t<R, F, list_type> (f, list_type(B1(a1)));
}
struct Convertible
{
Convertible(int a) : b(a) {}
int b;
};
int foo(Convertible bar)
{
return 2+bar.b;
}
void mainFunc()
{
int x = 3;
b::function<int()> funcObj = mybind(foo, x);
printf("val: %d\n", funcObj());
}
Because the functor may support multiple overloads, which may give different behaviours. Even if this signature could be resolved when you knew all the arguments (and I don't know if Standard C++ can guarantee this facility) bind does not know all the arguments, and therefore it definitely cannot be provided. Therefore, bind does not possess the necessary information.
Edit: Just to clarify, consider
struct x {
void operator()(int, std::vector<float>);
void operator()(float, std::string);
};
int main() {
auto b = std::bind(x(), 1); // convert or not?
}
Even if you were to reflect on the struct and gain the knowledge of it's overloads, it's still undecidable as to whether you need to convert the 1 to a float or not.
There are different cases where you need the arguments to be processed at the call site.
The first such example is calling a member function, where you can either have the member called on a copy of the object (boost::bind( &std::vector<int>::push_back, myvector)) which most probably you don't want, or else you need to pass a pointer and the binder will dereference the pointer as needed (boost::bind( &std::vector<int>::push_back, &myvector )) --Note both options can make sense in different programs
Another important use case is passing an argument by reference to a function. bind will copy performing the equivalent to a pass-by-value call. The library offers the option of wrapping arguments through the helper functions ref and cref, both of which store a pointer to the actual object to be passed, and at the place of call they dereference the pointer (through an implicit conversion). If the conversion to the target type was performed at bind time, then this would be impossible to implement.
I think this is due to the fact that bind has to work with any callable entity, be it a function pointer, std::function<>, or your own functor struct with operator(). This makes bind generic on any type that can be called using (). I.e. Bind's implicit requirement on your functor is just that it can be used with ()
If bind was to store the function argument types, it would have to somehow infer them for any callable entity passed in as a type parameter. This would obviously not be as generic, since deducing parameter types of an operator() of a passed-in struct type is impossible without relying on the user to specify some kind of typedef (as an example). As a result the requirement on the functor (or concept) is no longer concrete/simple.
I am not entirely sure this is the reason, but it's one of the things that would be a problem.
EDIT: Another point as DeadMG mentions in another answer, overloads would create ambiguities even for standard function pointers, since the compiler would not be able to resolve the functor type. By storing the types you provide to bind and using (), this problem is also avoided.
A good example would binding "std::future"s to some ordinary function taking ordinary types:
Say I want to use an ordinary f(x,y) function in an incredibly asynchronous way. Namely, I want to call it like "f(X.get(), Y.get())". There's a good reason for this- I can just call that line and f's logic will run as soon as both inputs are available (I don't need separate lines of code for the join). To do this I need the following:
1) I need to support implicit conversions "std::future<T> -> T". This means std::future or my custom equivalent needs a cast operator:
operator T() { return get(); }
2) Next, I need to bind my generic function to hide all its parameters
// Hide the parameters
template<typename OUTPUT, typename... INPUTS>
std::function<OUTPUT()> BindVariadic(std::function<OUTPUT(INPUTS...)> f,
INPUTS&&... in)
{
std::function<OUTPUT()> stub = std::bind( f, std::forward<INPUTS>(in)...);
return stub;
}
With a std::bind that does the "std::function<T> -> T" conversion at call time, I only wait for all the input parameters to become available when I ACTUALLY CALL "stub()". If it did the conversion via operator T() at the bind, the logic would silently force the wait when I actually constructed "stub" instead of when I use it. That might be fatal if "stub()" cannot always run safely in the same thread I built it.
There are other use cases that also forced that design choice. This elaborate one for async processing is simply the one I'm personally familiar with.