Please consider the following example:
#include <string>
#include <vector>
using std::string;
using std::vector;
template <typename T>
const T GetValue()
{
return T(); // some value
}
template <typename T>
const vector<T> GetValue()
{
return vector<T>(); // some vector of values
}
int main(int argc, char* argv[])
{
int i = GetValue<int>();
vector<int> = GetValue<vector<int>>();
return 0;
}
I have two template functions which are supposed to parse values from some storage depending on an given type. The first should do the job for simple data types, the second for vectors of simple data types only.
My problem is that the template matching is ambiguous since T may be vector<T>.
I wonder how to implement the overload/specialization for the vector types properly.
Any help would be greatly appreciated!
One simple way is to use an out-param, so that the template parameter can be deduced from the argument:
#include <vector>
using std::vector;
template <typename T>
void GetValue(T &t)
{
t = T(); // some value
}
template <typename T>
void GetValue(vector<T> &v)
{
v = vector<T>(); // some vector of values
}
int main(int argc, char* argv[])
{
int i;
GetValue(i);
vector<int> v;
GetValue(v);
return 0;
}
GetValue(v) isn't ambiguous, since the template argument deduction rules say that the second overload is the better match.
This isn't necessarily the interface/style you want, though, in which case you could use partial specialization instead of overloading. But that requires a class, since function templates cannot be partially specialized:
#include <vector>
using std::vector;
template <typename T>
struct Getter {
T get(void) {
return T(); // some value
}
};
template <typename T>
struct Getter<vector<T> > {
vector<T> get(void) {
return vector<T>(); // some vector of values
}
};
template <typename T>
T GetValue(void)
{
return Getter<T>().get();
}
int main(int argc, char* argv[])
{
int i = GetValue<int>();
vector<int> v = GetValue<vector<int> >();
return 0;
}
Both version ofGetValue differs by only return type, hence it is not overload.
I would suggest you to have just one GetValue and then implement two functions which differ by parameter type, as opposed to return type, and forward the call as:
namespace details
{
template <typename T>
T FillValue(T*)
{
//your code
}
template <typename T>
vector<T> FillValue(vector<T> *)
{
//your code
}
}
template <typename T>
T GetValue()
{
return details::FillValue((T*)0); //pass null pointer of type T*
}
The correct FillValue will be selected by the compiler based on the type of the argument passed to the function, which is T*. If T is vector<U> for some type U, then the second function will be selected, otherwise the first function will be selected.
You can move the partial specialization to a helper class:
#include <vector>
template <typename T>
class Creator {
public:
T operator()() const { return T(); }
};
template <typename T>
class Creator<std::vector<T> > {
public:
std::vector<T> operator()() const { return std::vector<T>(); }
};
template <typename T>
T GetValue() {
return Creator<T>()();
}
int main() {
int i = GetValue<int>();
std::vector<char> v = GetValue<std::vector<char> >();
}
Put the general method inside a class (naming as GetValue preferably) and declare that method as operator T(). Now specialize the class for vector<T>:
template <typename T>
struct GetValue
{
operator const T () const
{
std::cout<<"GetValue()\n";
return T(); // some value
}
};
template <typename T>
struct GetValue<vector<T> >
{
operator const vector<T> ()
{
std::cout<<"GetValue<vector<T>>()\n";
return vector<T>(); // some vector of values
}
};
Usage:
int i = GetValue<int>();
vector<int> v = GetValue<vector<int> >();
Demo
Related
I have a template class, with an internal method that is itself templated.
Consider the following minimal working example
#include <functional>
template<typename T>
class P{
public:
template <typename U>
P<U> call(std::function< P<U> (T)> f){
return f(return_value);
}
T return_value;
};
P<int> foo() {
P<int> value = P<int>();
return value;
}
P<float> bar(int arg) {
return P<float>();
}
int main()
{
auto res = foo().call<float>(bar);
return 0;
}
As you can see in the main function, the compiler forces me to to specify the float type for calling the call() function, eventhough the type should be obvious from passing over the bar() function, that specifies the float type.
Is it somehow possible to deduct the type so that the code in the main function can be simplified to the following statement:
auto res = foo().call(bar);
std::function is not the type that you should use whenever you want to pass a function around. std::function is a type that uses type erasure to be able to store different types of callables in one type. If you don't need that then you need no std::function:
#include <functional>
template<typename T>
class P{
public:
template <typename F>
auto call(F f){
return f(return_value);
}
T return_value{}; // don't forget to initialize !
};
P<int> foo() {
P<int> value = P<int>();
return value;
}
P<float> bar(int arg) {
return P<float>();
}
int main()
{
auto res = foo().call(bar);
return 0;
}
Using partial specializatzion you can get the return type of bar and you can get the float from P<float>:
#include <type_traits>
#include <iostream>
template <typename T> class P;
// get return type from function
template <typename T> struct return_type;
template <typename R,typename...args>
struct return_type<R(args...)> { using type = R; };
// get T from P<T>
template <typename P> struct P_arg;
template <typename T> struct P_arg< P<T> > { using type = T; };
// combine both
template <typename F>
struct get {
using type = typename P_arg<typename return_type<F>::type >::type;
};
template<typename T>
class P{
public:
template <typename F>
auto call(F f){
return f(return_value);
}
T return_value{};
};
P<float> bar(int arg) {
return P<float>();
}
int main()
{
std::cout << std::is_same_v< get<decltype(bar)>::type,float>;
return 0;
}
Though that does not really help here, because you cannot use it to decalre the return type of P::call, as it requires P<float> to be already complete.
Basicly ,I want to make a function behave differently for a vector(type) parameter and a non-vector type parameter .
#include <vector>
using namespace std;
template <typename type>
struct is_vector {
static const bool value = false;
};
template <typename type>
struct is_vector<vector<type>>
{
static const bool value = true;
};
template <typename type>
type read()
{
if (is_vector<type>::value)
{
type vec(10);
vec.front()=1;//left of '.front' must have class/struct/union
return vec;
}
else
{
return{};
}
}
int main()
{
auto i= read<int>();
}
I want to return a vector while using vector as the typename ,return an int while using int as the typename .
But since is_vector(int)::value returns false ,why would my compiler reports "left of '.front' must have class/struct/union" ?How can I make it work ?
What I want to achieve is to correctly deserialize a string to a vector(type) or a vector(vector(type)) .
I need to recursively call the read function ,while passing a multidemonsional vector as a template parameter ,but the compiler forbids me to do it .
template <typename type>
struct is_vector {
static const bool value = false;
};
template <typename type>
struct is_vector<vector<type>>
{
static const bool value = true;
};
template <typename type>
type read(char*& str)
{
if (is_vector<type>::value)
{
type vec(read<uint8_t>(str));
for (auto& e : vec)
e = read<type::value_type>(str);
return vec;
}
return *reinterpret_cast<type*>((str += sizeof(type)) - sizeof(type));
}
So I tried specialization .
template<>
vector<int> read<vector<int>>(char*& str)
{
vector<int> vec(read<uint8_t>(str));
for (auto& e : vec)
e = read<int>(str);
return vec;
}//works
template <typename type>
template <>
vector<type> read<vector<type>>(char*& str)
{
vector<type> vec(read<uint8_t>(str));
for (auto& e : vec)
e = read<type>(str);
return vec;
}//don't work
Do I really need to manually rewrite my read function for every kind of types I use ?
(like vector(vector(vector(int)))?)
You want a function template foo<R> that is parameterized at least
by return type R, and you want a specialized implementation
when R = std::vector<U>, for arbitrary type U.
It doesn't matter what the arguments of foo<R> may be, so for illustration
we'll assume there aren't any. Here's how you do that:
Define a trait template as follows:
template<typename T>
struct is_vector
{
static constexpr bool value = false;
};
template<template<typename...> class C, typename U>
struct is_vector<C<U>>
{
static constexpr bool value =
std::is_same<C<U>,std::vector<U>>::value;
};
With this,
is_vector<T>::value
will be true at compiletime if and only if T = std::vector<U>, for some U.
Then define two overloads of foo<R>() on the following lines:
template <typename R>
std::enable_if_t<!is_vector<R>::value,R> foo()
{
// Your non-vector implementation instead of...
std::cout <<
"In non-vector specialization of `foo<R>()`\n";
return R();
}
template <typename R>
std::enable_if_t<is_vector<R>::value,R> foo()
{
// Your vector implementation instead of...
std::cout <<
"In vector specialization of `foo<R>()`\n";
return R();
}
These two overloads are mutually exclusive and jointly exhaustive. The
first overload pans out to be legal code if and only if is_vector<R>::value is false. The
second overload pans out to be legal code if and only if is_vector<R>::value is true.
That's thanks to the behaviour of std::enable_if,
which you should study and understand.
When the compiler needs to pick one these template overloads to implement some
call foo<type>() that it finds in your code, it discovers that exactly one of the overloads
won't even compile when type is plugged in for the template parameter R. The first one won't compile if
type is some std::vector<U> and the second one won't compile if type is not some
std::vector<U>. Helpfully, the compiler picks the one that it can compile.
That's called SFINAE ("Substitution Failure Is Not An Error"),
and it's the solution of your problem.
Here's an illustrative program:
#include <vector>
#include <type_traits>
#include <iostream>
template<typename T>
struct is_vector
{
static constexpr bool value = false;
};
template<template<typename...> class C, typename U>
struct is_vector<C<U>>
{
static constexpr bool value =
std::is_same<C<U>,std::vector<U>>::value;
};
template <typename R>
std::enable_if_t<!is_vector<R>::value,R> foo()
{
// Your non-vector implementation instead of...
std::cout <<
"In non-vector specialization of `foo<R>()`\n";
return R();
}
template <typename R>
std::enable_if_t<is_vector<R>::value,R> foo()
{
// Your vector implementation instead of...
std::cout <<
"In vector specialization of `foo<R>()`\n";
return R();
}
int main()
{
auto i = foo<int>();
(void)i;
auto vc = foo<std::vector<char>>();
(void)vc;
return 0;
}
which will output:
In non-vector specialization of `foo<R>()`
In vector specialization of `foo<R>()`
(gcc 6.1/clang 3.8, -std=c++14 see live)
Suppose I have a template function:
template<typename T>
T produce_5_function() { return T(5); }
How can I pass this entire template to another template?
If produce_5_function was a functor, there would be no problem:
template<typename T>
struct produce_5_functor {
T operator()() const { return T(5); }
};
template<template<typename T>class F>
struct client_template {
int operator()() const { return F<int>()(); }
};
int five = client_template< produce_5_functor >()();
but I want to be able to do this with a raw function template:
template<??? F>
struct client_template {
int operator()() const { return F<int>(); }
};
int five = client_template< produce_5_function >()();
I suspect the answer is "you cannot do this".
I suspect the answer is "you cannot do this".
Yes, that is the case, you cannot pass a function template as a template argument. From 14.3.3:
A template-argument for a template template-parameter shall be the
name of a class template or an alias template, expressed as
id-expression.
The template function needs to be instantiated before you pass it to the other template. One possible solution is to pass a class type that holds a static produce_5_function like so:
template<typename T>
struct Workaround {
static T produce_5_functor() { return T(5); }
};
template<template<typename>class F>
struct client_template {
int operator()() const { return F<int>::produce_5_functor(); }
};
int five = client_template<Workaround>()();
Using alias templates, I could get a little closer:
template <typename T>
T produce_5_functor() { return T(5); }
template <typename R>
using prod_func = R();
template<template<typename>class F>
struct client_template {
int operator()(F<int> f) const { return f(); }
};
int five = client_template<prod_func>()(produce_5_functor);
How about wrapping that function?
template<typename T>
struct produce_5_function_wrapper {
T operator()() const { return produce_5_function<T>(); }
};
Then you can use the wrapper instead of the function:
int five = client_template< produce_5_function_wrapper >()();
Using the template function alone will not work, there's no such thing as "template template functions".
I would like to be able to name to a templated function in a template.
Since one can name a templated class using the "template template" syntax, and since one can name a function using the "function pointer" syntax, I was wondering whether there is a syntax (or a proposal) to name a function in a template without specifying to templates.
template<typename t_type>
struct A {
t_type value;
};
template<template<typename> class t_type>
struct B {
t_type<int> value;
};
template<int added>
constexpr int C (int value) {
return value + added;
}
template<int (*function)(int)>
constexpr int D (int value) {
return function(value);
}
// GOAL: Template argument referring to templated function
/*template<template<int> int (*function)(int)>
constexpr int E (int value) {
return function<1>(value);
}*/
int main() {
B<A> tt_good;
int fp_good = D< &C<1> >(0);
/*int fp_fail = E< &C >(0);*/
return 0;
}
One possible work-around for anyone interested in this functionality to first wrap the function D in a struct with a call method named (for example) "method", pass the struct into E as a "template template" parameter, and then call "method" in E.
The reason that I don't like this approach is that it requires a wrapper structure for every variadic function that might be used in this way.
Unfortunately, you cannot pass function templates as template parameters. The closest you can get is by using generic functors:
#include <iostream>
template <typename F>
void call(F f)
{
f("hello, world\n");
}
int main()
{
call([](auto value) { std::cout << value; });
}
If you don't have C++14 generic lambdas, you can write your own functors by hand:
#include <iostream>
template <typename F>
void call(F f)
{
f("hello, world\n");
}
struct print
{
template <typename T>
void operator()(T value) const
{
std::cout << value;
}
};
int main()
{
call(print());
}
My issue here is not that I can't map to function pointers, but more the other way around.
With my current setup, I can instantiate classes through strings.
Now, I'm trying to get strings from class types.
My proposed method:
class A {};
template <typename T> T* create(void) { return new T; }
static std::map<std::string,A*(*)(void)> str_to_class;
static std::map<A*(*)(void),std::string> class_to_str;
template <typename T> void Bind(std::string identity) {
// T must inherit from A.
str_to_class[identity]=&create<T>;
class_to_str[&create<T>]=identity;
}
A* MakeFromString(std::string identity) {
return str_to_class[identity](); // Compiles fine.
}
template <typename T> std::string GetTypeString(void) {
return class_to_str[&create<T>]; // Error!
}
int main(int,char**) {
Bind<A>("A");
A* new_entity=CreateFromString("A");
}
Error: C2679: binary '[' : no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion)
I know I can use dynamic_cast<> to check entity types, but that would require writing code for every class that would be used.
The problem is that create() returns a type different than what is specified as the return type of the maps key template argument. Since everything uses A as the base / primary class type you should consider doing the same for create().
template <typename T> A* create(void) { return new T; }
^^^^
I have done something similar which is about mapping string to function pointer of any type. From my answer which was posted here:
#include <string>
#include <iostream>
#include <map>
#include <vector>
int fun1(){
std::cout<<"inside fun1\n";
return 2;
}
void fun2(void){
std::cout<<"inside fun2\n";
}
int fun3(int a){
std::cout<<"inside fun3\n";
return a;
}
std::vector<int> fun4(){
std::cout<<"inside fun4\n";
std::vector<int> v(4,100);
return v;
}
// every function pointer will be stored as this type
typedef void (*voidFunctionType)(void);
struct Interface{
std::map<std::string,voidFunctionType> m1;
template<typename T>
void insert(std::string s1, T f1){
m1.insert(std::make_pair(s1,(voidFunctionType)f1));
}
template<typename T,typename... Args>
T searchAndCall(std::string s1, Args&&... args){
auto mapIter = m1.find(s1);
/*chk if not end*/
auto mapVal = mapIter->second;
// auto typeCastedFun = reinterpret_cast<T(*)(Args ...)>(mapVal);
auto typeCastedFun = (T(*)(Args ...))(mapVal);
return typeCastedFun(std::forward<Args>(args)...);
}
};
int main(){
Interface a1;
a1.insert("fun1",fun1);
a1.insert("fun2",fun2);
a1.insert("fun3",fun3);
a1.insert("fun4",fun4);
int retVal = a1.searchAndCall<int>("fun3",2);
a1.searchAndCall<void>("fun2");
auto temp = a1.searchAndCall<std::vector<int>>("fun4");
return 0;
}