templated parameter deduction in C++ - c++11

Is there any way to construct this code so that I do not have to specify the template parameter of bar?
i.e. it does not currently compile, but will compile if I change bar(v) to bar<int>(v) in main.
#include <cstdlib>
#include <vector>
template <class T>
struct foo
{
foo(std::vector<T>& v)
{
}
};
template <class T>
void bar(const foo<T>& f)
{
}
int main()
{
std::vector<int> v;
bar(v); // does not compile
bar<int>(v); // compiles but is undesirable
return EXIT_SUCCESS;
}

The compiler is only allowed one implicit conversion but you can add an overload for bar that tries to convert whatever you give it to a foo and then calls your original bar with the temporary foo (which is what would happen if two implicit conversions was allowed in your original code):
template<typename T>
void bar(T& v) {
return bar(foo(v));
}
Since the conversion constructor in foo doesn't take the argument by const&, neither can this bar overload.

Related

How to elide type of temporary object in a variadic function call?

When is it possible to elide types of temporaries passed into a variadic function template? Overload resolution doesn't seem to work. Consider this:
#include <vector>
struct option
{
std::vector<int> to_wait;
std::vector<int> to_set;
};
namespace fsm
{
template <typename... Ts>
void generic_wait(Ts... Args) {
std::array<option, sizeof...(Ts)> hello = {{Args...}};
}
}
int main()
{
fsm::generic_wait(option{{2}, {3}}); // <-- This compiles
// fsm::generic_wait({{2}, {3}}); // <-- This I would like to compile
}
This compiles only when I directly specify the temporary type. If I leave it off it stops working (C++11). Can I do something to make it work?

How to make a particular constructor on a tempate type available only for a particular specialization in C++11?

I have a C++11 template that can be specialized with an arbitrary type parameter.
template<class ElementType>
class Foo
How do I declare a constructor that appears for the compiler's consideration only when ElementType is e.g. const uint8_t?
That is, I have a bunch of constructors that are generic over any ElementType, but I also want to have constructors that are only considered when ElementType is specialized in a particular way. (Allowing those constructors to be selected for other types would be unsafe.)
So far std::enable_if examples that I've found have been conditional on the types of the arguments of the constructors.
template<class ElementType>
struct Foo
{
template <typename T = ElementType>
Foo(typename std::enable_if<!std::is_same<T, const uint8_t>{}>::type* = nullptr) {}
template <typename T = ElementType>
Foo(typename std::enable_if<std::is_same<T, const uint8_t>{}>::type* = nullptr) {}
};
int main()
{
Foo<int> a{}; // ok, calls first constructor
Foo<const uint8_t> b{}; // ok, calls second constructor
}
wandbox example
You can break the class into two classes. The derived class' purpose is to be able to specialize constructors for different types. E.g.:
#include <cstdio>
#include <cstdint>
template<class ElementType>
struct Foo_
{
Foo_() { std::printf("%s\n", __PRETTY_FUNCTION__); }
};
template<class ElementType>
struct Foo : Foo_<ElementType>
{
using Foo_<ElementType>::Foo_; // Generic version.
};
template<>
struct Foo<uint8_t> : Foo_<uint8_t>
{
Foo() { std::printf("%s\n", __PRETTY_FUNCTION__); } // Specialization for uint8_t.
};
int main(int ac, char**) {
Foo<int8_t> a;
Foo<uint8_t> b;
}
The benefit of using the derived class here compared to enable_if is that:
The class can be partially specialized.
Only one specialization of the class is chosen for particular template parameters, rather than a set of constructors. When adding specializations for new types the existing enable_if expressions may need to be changed to make them more restrictive to avoid function overload set resolution ambiguity.

C++ 11 Comparing parameter packs

I am trying to wrap my head around parameter packs and need a little help.
Looking at the contrived example below, Is there a way to compare Args to T and only allow bar() to compile if they match? For example if I create Task<void(int, char, float)> I want bar(float, char, float) not to compile but bar(int, char, float) to compile just fine. Is this even feasible?
template <typename... Types>
struct foo {};
template<typename T>
struct Task;
template<typename R, typename...Args>
struct Task<R(Args...)>
{
template<typename... T>
std::enable_if<is_same<T, Args>
void bar(T... args)
{
//do something here
}
};
int main()
{
Task<int(int)> task;
int a = 0;
float b = 1.0;
bool c = false;
//compiles
task.bar(a);
//none of these should compile
task.bar(b);
task.bar(c);
task.bar(a, b);
task.bar(a, b, c);
}
First, syntax should be:
template<typename R, typename...Args>
struct Task<R(Args...)>
{
template<typename... T>
std::enable_if<is_same<tuple<T...>, tuple<Args...> >::value > bar(T... args)
{
//do something here
}
};
Which compiles fine, because of SFINAE: while trying to instantiate bar(bool) for example, first instantiation fails with bool type, but an instantiation exists when performing conversion of parameter to int.
To get desired effect, you need the hard type check to happen after instantiating the template:
#include <type_traits>
#include <tuple>
template<typename T>
struct Task;
template<typename R, typename... Args>
struct Task<R(Args...)>
{
template<typename... OtherArgs>
void bar(OtherArgs... otherArgs)
{
static_assert(
std::is_same<std::tuple<Args...>, std::tuple<OtherArgs...> >::value,
"Use same args types !"
);
// Do something
}
};
int main()
{
Task<int(int)> task;
// Compiles fine
task.bar(1);
// Fails to compile
task.bar('u');
task.bar(0ul);
return 0;
}

Compile error in calling a function with std::function argument

The minimal code below gives me a compile error:
#include <iostream>
#include <functional>
using namespace std;
template<typename ActionType, typename... Cols>
void print_action(function<ActionType*(Cols..., ActionType)> action_factory)
{
}
int main(int argc, char *argv[])
{
print_action<string, uint8_t>(function<string*(uint8_t, string)>());
return 0;
}
The error is:
foo.cc: In function ‘int main(int, char**)’:
foo.cc:13:69: error: no matching function for call to ‘print_action(std::function<std::basic_string<char>*(unsigned char, std::basic_string<char>)>)’
print_action<string, uint8_t>(function<string*(uint8_t, string)>());
^
foo.cc:13:69: note: candidate is:
foo.cc:7:6: note: template<class ActionType, class ... Cols> void print_action(std::function<ActionType*(Cols ..., ActionType)>)
void print_action(function<ActionType*(Cols..., ActionType)> action_factory)
^
foo.cc:7:6: note: template argument deduction/substitution failed:
foo.cc:13:69: note: mismatched types ‘std::basic_string<char>’ and ‘unsigned char’
print_action<string, uint8_t>(function<string*(uint8_t, string)>());
^
foo.cc:13:69: note: ‘std::function<std::basic_string<char>*(unsigned char, std::basic_string<char>)>’ is not derived from ‘std::function<std::basic_string<char>*(Cols ..., std::basic_string<char>)>’
I also try to change the input parameter to a simple pointer function by below code:
#include <iostream>
#include <functional>
using namespace std;
template<typename ActionType, typename... Cols>
void print_action(ActionType*(*action_factory)(Cols..., ActionType))
{
}
string* foo_factory(uint8_t cols, string act)
{
}
int main(int argc, char *argv[])
{
print_action<string, uint8_t>(foo_factory);
return 0;
}
It gives me the same error. After some works my last guess is that it is a bug of g++ because if I change the variadic template parameter to a simple parameter no errors happen.
Am I right or I missed some syntax of c++?
I use g++-4.8.4 with c++11 flag(I checked it using clang-3.4 and g++-4.9.2).
EDIT:
If I change the code to this:
#include <iostream>
#include <functional>
using namespace std;
template<typename ActionType, typename... Cols>
struct Foo
{
Foo()
{}
void print_action(function<ActionType*(Cols..., ActionType)> action_factory)
{
}
};
int main(int argc, char *argv[])
{
Foo<string, uint8_t> f;
f.print_action(function<string*(uint8_t, string)>());
return 0;
}
I get no error. I don`t understand this behavior because in both situations I defined the template parameters explicitly and I did not expect any deduction, but It seems that compiler does some deduction when it is a template function but not when it is a member function of a template class.
The issue is that you have (Cols..., ActionType). One might think that the compiler should notice that Cols... should be all the arguments before the end so long as the end is the same as ActionType, but this is not how the language works.
A simple solution would to just deduce the entire argument list. Compilation will fail anyway if you happen to use the final argument as in a way the type doesn't support, and you could always add in a static_assert to ensure that the final parameter is the same as ActionType if you really wanted.
template<typename ActionType, typename... Cols>
void print_action(function<ActionType*(Cols...)> action_factory)
{
//Maybe with a static_assert like this
using LastArg = typename std::tuple_element<
sizeof...(Cols)-1, //number of args - 1
std::tuple<Cols...>
>::type;
static_assert(std::is_same<LastArg, ActionType>::value,
"The final argument must be the same type as ActionType");
}
Live Demo
Usually variadic templates are written thus
template<typename First, typename... Rest> class test;
The compiler matches the first argument and leaves the rest (empty or more) to variadic part. The behaviour when reversed is not as expected. Variadic template arguments are greedy, in that, all arguments are eaten-up by it, leaving none to the last.
Your example code compiles fine, when the order is reversed:
template<typename ActionType, typename... Cols>
void print_action(function<ActionType*(ActionType, Cols...)>) {
}
int main()
{
print_action(function<string*(string, uint8_t)>());
}
Live example.
There's a difference between argument type deduction and instantiation. Quote from C++ Templates: The Complete Guide:
The process of replacing template parameters by concrete types is called instantiation. It results in an instance of a template.
When a function template is instantiated, we get a function out of it; same for class/struct.
It seems that compiler does some deduction when it is a template function but not when it is a member function of a template class.
There is no type deduction or instantiation happening for the function call. It is not a function template, but just a function. The call is just another ordinary function call.
However, the struct is really a struct template and a struct is created out of the template, when an object was created. For this struct template instantiation
template<typename ActionType, typename... Cols>
struct Foo;
the order is correct (the variadic argument is the last) and so it works.

Function object vs. function in a header-only library

I am writing a library that I would like to keep header-only. In the code I have something like this:
// Wrapper.h
#ifndef INCLUDED_WRAPPER_H
#define INCLUDED_WRAPPER_H
namespace quux {
template <typename T, typename U>
class Wrapper
{
T m_t;
U m_u;
public:
Wrapper(T const & t, U const & u) : m_t(t), m_u(u) { }
// ...
};
} // namespace quux
#endif // INCLUDED_WRAPPER_H
// Foo.h
#ifndef INCLUDED_FOO_H
#define INCLUDED_FOO_H
#include <type_traits>
#include "Wrapper.h"
namespace quux {
// if some type is special, then there will be a specialization of this
// struct derived from std::true_type
template <typename T> struct is_special : std::false_type { };
class Foo
{
template <typename T>
Wrapper<Foo, T> impl(T const & t, std::true_type ) const
{
return Wrapper<Foo, T>(*this, t);
}
template <typename T>
T const & impl(T const & t, std::false_type ) const;
{
return t;
}
public:
template <typename T>
auto operator()(T const & t) const // using automatic return type deduction
{
return impl(t, is_special<T>());
}
};
#if 1
Foo const foo;
#else
template <typename T>
auto foo(T const & t) // using automatic return type deduction
{
return Foo()(t);
}
#endif
} // namespace quux
#endif // INCLUDED_FOO_H
I see two different ways to have a callable entity with the name "quux::foo": a constant object named foo (the #if 1 - branch) or a function named foo that forwards its arguments to a Foo-object (the #else-branch). Which version should I prefer? A const Object has internal linkage so there are no linker errors if the header is included in multiple translation units. Are there any salient differences between the two approaches?
As you are calling a function, and your function object has no state, I would go with the function interface.
First, because functions can be overloaded, while function objects cannot outside of the body of the function object. You may wish to enable ADL extensions to your function.
Second because function objects are wierd. They cannot be converted to function pointers (in your case for no good reason), for example (note you can fix that with more boilerplate). Weird solutions are only a good idea when simple solutions are insufficient: in this case the simple perfect forwarding function is simpler.
Finally you might want to make your functions perfect forward, and have T&& rvalues give functions that return T at the outermost API level. This enables lifetime extension of temporaries to pass through your functions.

Resources