Automatic template instantiation - c++

Given the class template
template<class T>
struct A {
A( const T & x );
};
I would like to instantiate objects of this class without writing out the actual type T, because this is typically a clumsy type resulting from some sort of expression templates and lambda functions. One way to accomplish this would be
template<class T>
A<T> create_A( const T& t ){
return A<T>( t );
}
int main(){
auto a = create_A( complicated_expression );
}
Here I never wrote the actual type of the expression, but this creates a copy of A and won't work without a copy constructor. I don't have a copy (or move) constructor. What I'm looking for is something like
A a( complicated_expression );
Clean and simple, and the compiler should be able to figure out the actual type. Unfortunately this isn't valid C++. So what would be the best valid C++ syntax to accomplish the same thing? Currently I'm doing this:
auto x = complicated_expression;
A<decltype(x)> a(x);
But this seems unnecessary verbose. Is there a better way to do this?

The code
template<class T>
A<T> create_A( const T& t ){
return A<T>( t );
}
int main(){
auto a = create_A( complicated_expression );
}
formally requires copy or move constructor to be defined and available, but any reasonable compiler will be able to optimize it away using copy elision rule. It is the standard idiom used widely across the standard library (e.g. std::make_pair).

Well, if your compiler is MSVC, this will work:
template<class T>
struct A {
A(const T & x) {}
A(const A&) = delete;
A(A&&) = delete;
};
template <typename T>
A<T> create_A(const T& t)
{
return t;
}
const auto& a = create_A(666);
const auto& b = create_A(a);
const auto& c = create_A(b);
No such luck with clang and g++, though.
Assigning a result returned by value to a const reference is perfectly legal, by the way, and has its uses. Why MSCV avoids checking for type being moveable/copyable (even though it would optimise it away) is a mystery to me and likely a bug. But, it'd kinda work in your case if you need to do it this way.
EDIT: alternatively, if you are not afraid to bring the wrath of C++ gods upon yourself, you can transform create_A into a macro:
#define create_A(x) (A<decltype(x)>(x))
Now it shall work on all compilers.
EDIT2: as #dyp suggested, this answer can be improved further:
template <typename T>
A<T> create_A(const T& t)
{
return { t };
}
auto&& a = create_A(666);
auto&& b = create_A(a);
auto&& c = create_A(b);
It will work on all C++11 compilers.

The technique you're trying to implement is called template argument deduction.
So, I don't think you can achive something like:
A a( complicated_expression );
Since here A is the template's name and the template argument deduction takes place only in functions. Not in classes. With the line above you will not be able to avoid the missing template arguments error.

Related

Cleaner way to specify type to get from a std::variant?

I've got code that can be simplified to
std::variant<float, int> v[2] = foo();
int a = std::get<decltype(a)>(v[0]);
float b = std::get<decltype(b)>(v[1]);
Obviously this can go throw if foo() returns the wrong variants, but that's not my problem here. (The real code has a catch). My problem is that the decltype(a) violates the Don't Repeat Yourself principle.
Is there a cleaner way to initialize a and b, and still throw if the types do not match expectations? In particular, I don't want a static_cast<int>(std::get<float>(v)) if the variant contains a float while I'm trying to initialize an int.
You could wrap your call to get in a template that implicitly converts to the target type.
template<typename... Ts>
struct variant_unwrapper {
std::variant<Ts...> & var;
template <typename T>
operator T() { return std::get<T>(var); }
};
See it on coliru
IMO it would be nice to allow template deduction to take over, so providing a helper function should do the job:
template<typename T, typename...VariantParams>
void get_from(const std::variant<VariantParams...>& v, T& value)
{
value = ::std::get<T>(v);
}
int a;
get_from(v[0], a);
As #paulo says in the comments, seems like the DRY solution is to use auto for the declaration, changing:
int a = std::get<decltype(a)>(v[0]);
to:
auto a = std::get<int>(v[0]);
You only name the type (int) and the variable (a) once each. Doesn't work if you separate declaration and initialization, so you'd still need:
int a;
...
a = std::get<decltype(a)>(v[0]);
in that case, but if you write all your C++ code deferring declarations until the point of definition, it's not needed often.

Allow implicit type conversion during template evaluation

I'm writing a wrapper class for C++ types, which allows me to instrument when a wrapped object is constructed, accessed, modified, and destroyed. To make this transparent for the original code, I include implicit conversion functions back to the underlying type, but this fails when a wrapped object is passed directly to a template since implicit conversions aren't evaluated. Here's some code that demonstrates this problem:
#include <utility>
// simplified wrapper class
template <typename T>
class wrap {
T t;
public:
wrap() : t() {}
wrap(const T& _t) : t(_t) {}
wrap(T&& _t) : t(std::move(_t)) {}
constexpr operator T&() { return t; }
constexpr operator const T&() const { return t; }
};
// an example templated function
template <typename T>
bool is_same(const T& t1, const T& t2) { return t1 == t2;}
// second invocation fails due to template substitution failure
bool problem() {
wrap<int> w(5);
return is_same(static_cast<int>(w), 5) && is_same<>(w, 5);
}
I can resolve this manually by performing a static_cast on the wrapped variable at each template call site (as shown in the first invocation), but this doesn't scale well since I'm working with a large code base. Similar questions suggest inlining each template function as a friend function, but this also requires identifying and copying each template, which doesn't scale.
I'd appreciate any advice on how to (1) workaround this conversion problem with templated functions, or (2) otherwise instrument a variable at source-level without this problem.
The fault in this example lies with is_same. It declares that it requires two arguments of the same type, which is a requirement it does not need, and fails to require that type to have an ==, which it does need.
Granted, it is common to find C++ that poorly constrains template functions because it is difficult and verbose to do otherwise. Authors take a practical shortcut. That said, isn't the approach to fix the interface of is_same?
// C++17 version. Close to std::equal_to<>::operator().
template <typename T, typename U>
constexpr auto is_same(T&& t, U&& u)
noexcept(noexcept(std::forward<T>(t) == std::forward<U>(u)))
-> decltype(std::forward<T>(t) == std::forward<U>(u))
{
return std::forward<T>(t) == std::forward<U>(u);
}
With a corrected is_same, the code just works.
There are other examples one can imagine which may require two arguments to have the same type. For example, if the return type depends on the argument type and the return value can come from either:
template <typename T>
T& choose(bool choose_left, T& left, T& right) {
return choose_left ? left : right;
}
This is much rarer. But it might actually require thought to decide whether to use the underlying or wrapper type. If you have this enhanced behavior in the wrapper type, and conditionally use a wrapped value or an underlying value, should the underlying value be wrapped to continue to get the enhanced behavior, or do we drop the enhancement? Even if you could make this silently choose one of those two behaviors, would you want to?
However, you can still make it easier to get the value than to say static_cast<T>(...), for example by providing an accessor:
// given wrap<int> w and int i
is_same(w.value(), 5);
choose_left(true, w.value(), i);
I have a few other important comments:
wrap() : t() {}
This requires T be default constructible. = default does the right thing.
wrap(const T& _t) : t(_t) {}
wrap(T&& _t) : t(std::move(_t)) {}
These are not explicit. A T is implicitly convertible to a wrap<T> and vice versa. This does not work well in C++. For example, true ? w : i is not well-formed. This causes std::equality_comparable_with<int, wrap<int>> to be false, which would be a reasonable requirement for is_same. Wrapper types should probably be explicitly constructed, and can be implicitly converted to the underlying type.
constexpr operator T&() { return t; }
constexpr operator const T&() const { return t; }
These are not ref-qualified, so they return lvalue references even if the wrapper is an rvalue. That seems ill-advised.
Finally, construction and conversion only take into account the exact type T. But any place T is used, it might be implicitly converted from some other type. And two conversions are disallowed in C++. So for a wrapper type, one has a decision to make, and that often means allowing construction from anything a T is constructible from.
With a pointer wrapper function it can work, if you treat the "inner" guy as a pointer.
This is not a complete solution, but should be a good starting point for you (for instance, you need to carefully write the copy and move ctors).
You can play with this code in here.
Disclaimer: I took the idea from Andrei Alexandrescu from this presentation.
#include <iostream>
using namespace std;
template <typename T>
class WrapperPtr
{
T * ptr;
public:
WrapperPtr(const WrapperPtr&){
// ???
}
WrapperPtr(WrapperPtr&&) {
// ???
}
WrapperPtr(const T & other)
: ptr(new T(other)) {}
WrapperPtr(T * other)
: ptr(other) {}
~WrapperPtr()
{
// ????
delete ptr;
}
T * operator -> () { return ptr; }
T & operator * () { return *ptr; }
const T & operator * () const { return *ptr; }
bool operator == (T other) const { other == *ptr; }
operator T () { return *ptr; }
};
// an example templated function
template <typename T>
bool my_is_same(const T& t1, const T& t2) { return t1 == t2;}
bool problem() {
WrapperPtr<int> w(5);
return my_is_same(static_cast<int>(w), 5) && my_is_same(*w, 5);
}

std::initializer_list alternatives for noncopyable types

I know that trying to use a std::initializer_list<NonCopyable> leads to an error because the elements are copied into the temporary array represented by the initializer_list. I have also read some explanation on why it would not be alright to have rvalue references in the list, which I'm fine with.
The problem is that I would like to pass noncopyable things not in order to move from them, but only const-access them, so the argument about rvalues does not apply. What can I do to retain, if possible, the list initialization syntax and the reference semantics (no wrappers, no raw pointers)?
NonCopyable a{...}, b{...};
ListInitialized c{a, b};
I think I'm missing something extremely obvious here.
Update:
This works(*),
ListInitialized(std::initializer_list<std::reference_wrapper<NonCopyable>>) {...}
but won't accept rvalues. It would be nice if I could simply pass a list of anything that could go into const NonCopyable&.
(*) I know I wrote "no wrappers" but this affects neither the calling code nor the iteration over the list.
You can give ListInitialized a variadic constructor template:
struct ListInitialized
{
template <class... T>
ListInitialized(const T... &arg);
};
If you need to make sure it can only be instantiated with the correct type, consider suitable SFINAE:
struct ListInitialized
{
template <
class... T,
class Sfinae = std::enable_if_t<std::is_same<std::decay_t<T>, NonCopyable> &&...
>
ListInitialized(const T... &arg);
};
In addition to the comments and answers above, I found that this minimalistic wrapper fulfills my needs:
#include <initializer_list>
#include <utility>
struct S {
S() { }
S(const S&) = delete; // Non-copyable
void f() const { }
};
template<class T>
class const_reference_wrapper {
public:
const_reference_wrapper(const T& ref_) : ref(ref_) { }
operator const T&() const { return ref; }
private:
const T& ref;
};
struct T {
T(std::initializer_list<const_reference_wrapper<S>> l) : c(l.size()) {
for(const S& i : l) // note: const auto& can't be used here, but it would be the same for std::reference_wrapper
i.f(); // we can do something with the elements
}
int c;
};
int main() {
S a, b;
T t{a, b, S{}}; // we can mix lvalues and rvalues with a natural syntax
return t.c; // correctly returns 3
}
Of course, care needs to be taken to ensure that any rvalue passed through this will live through the time it is being referenced.

Pass a member function as Compare operator for C++ standard library algorithm

In my code I have now something like
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
[&bar](Foo const &lhs, Foo const &rhs) {
return bar.myWeakLessOperator(lhs, rhs);
});
I wonder wether it exists a way to simplify it by passing directly the member function myWeakLessOperator (that is not static) instead of writing a lambda function just to make to call.
I would like to obtain something like
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
/* something that rely to */ bar.myWeakLessOperator);
Any idea if it possible and how to do it ?
A possible solution is to use a struct that satisfies Compare inside Foo:
class Foo
{
public:
struct WeakLessOperator
{
bool operator()(const Foo& a, const Foo& b)
{
// implementation - take care of meeting requirements of Compare
return true;
}
};
WeakLessOperator myWeakLessOperator;
};
Foo bar;
auto minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
bar.myWeakLessOperator);
So you want to have a function object that represents a member function bound to a particular receiver. Unfortunately, there's nothing I could find in the standard or Boost that does that.
What you can do is write your own fairly easily.
template <typename R, typename T>
struct member_function_binder {
T *receiver;
R T::*pmf;
template <typename... Args>
auto operator()(Args&&... args) {
return (receiver->*pmf)(std::forward<Args>(args)...);
}
};
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return member_function_binder<R, T>{&receiver, pmf};
}
Have a look at the live demo, I think this might be what you want.
Even more concise, you don't need to have a separate class member_function_binder if you return a lambda from bind_member_function like so:
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return [pmf, &receiver](auto&&... args) {
return (receiver.*pmf)(std::forward<decltype(args)>(args)...);
};
}
Live demo
Solution to pass a unary member function like Foo::compareTo(const Foo &rhs), not what OP asked:
What you want is std::mem_fn; it's a wrapper that makes a member function pointer into a function object. You would use it like this:
auto min = std::min_element(
begin(mySet), end(mySet), std::mem_fn(&Foo::myWeakLessOperator));
you can use std::bind, or some other wrapper.
EXAMPLE:
using namespace std::placeholders;
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
std::bind(&Foo::myWeakLessOperator, bar, _1, _2));
OR
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
gnr::memfun<MEMFUN(Foo::myWeakLessOperator)>(bar));
The closest to what you want is maybe
auto minElement =
std::min_element(
std::begin(mySet),
std::end(mySet),
mem_fun_functor(&Foo::myWeakLessOperator)
);
There is std::mem_fun (deprecated in c++11) and std::mem_fn both wrap a member function pointer, though both take a instance as parameter to invoke the member function. If you want a functor that wraps the object also, i think you need to write your own:
auto mem_fun_functor =
[&bar](decltype(&Foo::myWeakLessOperator) f){
return [f,&bar](const Foo& a,const Foo& b) {
return (bar.*f)(a,b);
};
};
However, given that none of the answers is really much shorter or leading to cleaner code, I would consider to just use your first version with the lambda (unless you maybe have many different member functions that you want to use as comparator).
What do you actually mean by "simplifying" ? You do need to specify the object you want to call the member function on, you need to specify how you want to forward the parameters. Thats basically all the lambda does.
Defering all this to a functor as for example above makes your code more complicated rather than simpler. In your first snippet anybody familiar with standard algorithms can look at that few lines of code and fully understand what is going on.
Eventually it is a matter of style, and what you consider as readable, but being able to declare stuff in the most narrowest scope is one big advantage of using lambdas.

C++ template to cover const and non-const method

I have a problem with duplication of identical code for const and non-const versions. I can illustrate the problem with some code. Here are two sample visitors, one which modifies the visited objects and one which does not.
struct VisitorRead
{
template <class T>
void operator()(T &t) { std::cin >> t; }
};
struct VisitorWrite
{
template <class T>
void operator()(const T &t) { std::cout << t << "\n"; }
};
Now here is an aggregate object - this has just two data members but my actual code is much more complex:
struct Aggregate
{
int i;
double d;
template <class Visitor>
void operator()(Visitor &v)
{
v(i);
v(d);
}
template <class Visitor>
void operator()(Visitor &v) const
{
v(i);
v(d);
}
};
And a function to demonstrate the above:
static void test()
{
Aggregate a;
a(VisitorRead());
const Aggregate b(a);
b(VisitorWrite());
}
Now, the problem here is the duplication of Aggregate::operator() for const and non-const versions.
Is it somehow possible to avoid duplication of this code?
I have one solution which is this:
template <class Visitor, class Struct>
void visit(Visitor &v, Struct &s)
{
v(s.i);
v(s.i);
}
static void test2()
{
Aggregate a;
visit(VisitorRead(), a);
const Aggregate b(a);
visit(VisitorWrite(), b);
}
This means neither Aggregate::operator() is needed and there is no duplication. But I am not comfortable with the fact that visit() is generic with no mention of type Aggregate.
Is there a better way?
I tend to like simple solutions, so I would go for the free-function approach, possibly adding SFINAE to disable the function for types other than Aggregate:
template <typename Visitor, typename T>
typename std::enable_if< std::is_same<Aggregate,
typename std::remove_const<T>::type
>::value
>::type
visit( Visitor & v, T & s ) { // T can only be Aggregate or Aggregate const
v(s.i);
v(s.d);
}
Where enable_if, is_same and remove_const are actually simple to implement if you don't have a C++0x enabled compiler (or you can borrow them from boost type_traits)
EDIT: While writing the SFINAE approach I realized that there are quite a few problems in providing the plain templated (no SFINAE) solution in the OP, which include the fact that if you need to provide more than one visitable types, the different templates would collide (i.e. they would be as good a match as the others). By providing SFINAE you are actually providing the visit function only for the types that fulfill the condition, transforming the weird SFINAE into an equivalent to:
// pseudocode, [] to mark *optional*
template <typename Visitor>
void visit( Visitor & v, Aggregate [const] & s ) {
v( s.i );
v( s.d );
}
struct Aggregate
{
int i;
double d;
template <class Visitor>
void operator()(Visitor &v)
{
visit(this, v);
}
template <class Visitor>
void operator()(Visitor &v) const
{
visit(this, v);
}
private:
template<typename ThisType, typename Visitor>
static void visit(ThisType *self, Visitor &v) {
v(self->i);
v(self->d);
}
};
OK, so there's still some boilerplate, but no duplication of the code that depends on the actual members of the Aggregate. And unlike the const_cast approach advocated by (e.g.) Scott Meyers to avoid duplication in getters, the compiler will ensure the const-correctness of both public functions.
Since your ultimate implementations are not always identical, I don't think there's a real solution for your perceived "problem".
Let's think about this. We have to cater for the situations where Aggregate is either const or non-const. Surely we should not relax that (e.g. by providing only a non-const version).
Now, the const-version of the operator can only call visitors which take their argument by const-ref (or by value), while the non-constant version can call any visitor.
You might think that you can replace one of the two implementations by the other. To do so, you would always implement the const version in terms of the non-const one, never the other way around. Hypothetically:
void operator()(Visitor & v) { /* #1, real work */ }
void operator()(Visitor & v) const
{
const_cast<Aggregate *>(this)->operator()(v); // #2, delegate
}
But for this to make sense, line #2 requires that the operation is logically non-mutating. This is possible for example in the typical member-access operator, where you provide either a constant or a non-constant reference to some element. But in your situation, you cannot guarantee that the operator()(v) call is non-mutating on *this!
Therefore, your two functions are really rather different, even though they look formally similar. You cannot express one in terms of the other.
Maybe you can see this another way: Your two functions aren't actually the same. In pseudo-code, they are:
void operator()(Visitor & v) {
v( (Aggregate *)->i );
v( (Aggregate *)->d );
}
void operator()(Visitor & v) const {
v( (const Aggregate *)->i );
v( (const Aggregate *)->d );
}
Actually, coming to think of it, perhaps if you're willing to modify the signature a bit, something can be done:
template <bool C = false>
void visit(Visitor & v)
{
typedef typename std::conditional<C, const Aggregate *, Aggregate *>::type this_p;
v(const_cast<this_p>(this)->i);
v(const_cast<this_p>(this)->d);
}
void operator()(Visitor & v) { visit<>(v); }
void operator()(Visitor & v) const { const_cast<Aggregate *>(this)->visit<true>()(v); }
Normally with this type of thing, it's possibly better to use methods that make sense. For example, load() and save(). They say something specific about the operation that is to be carried out via the visitor. Typically both a const and non-const version is provided (for things like accessors anyway), so it only appears to be duplication, but could save you some headache debugging later down the line. If you really wanted a workaround (which I wouldn't advice), is to declare the method const, and all the members mutable.
Add visitor trait to tell whether it's modifying or not (const or non-const use).
This is used by STL iterators.
You could use const_cast and change VisitorRead's method signature so it also take's const T& as a parameter, but I think that is an ugly solution.
Another solution - require the Visitor class to have a metafunction that adds const when it applies:
template <class Visitor>
static void visit(Visitor &v, typename Visitor::ApplyConst<Aggregate>::Type &a)
{
v(a.i);
v(a.d);
}