I have the following code
template< typename T>
struct S{
T x,y;
S(T a, T b) : x(a) , y(b) {}
};
using Di = S<int>;
using Dd = S<double>;
auto foo(Dd d){
..........
}
Now my doubt is: suppose I am calling foo() with parameter of type Di then it's an error of incorrect reference type.
I know that one solution is to use auto here as it works . But in general I want to know is there any other method so that my function works for both parameter types.
You can make the function a template:
template<typename T>
auto foo(S<T> d){
// ...
}
Now you can call foo with any instantiation of S.
If you want to constrain the function template to only accept instantiations of S with either int or double, you can do that check inside the function:
template<typename T>
auto foo(S<T> d){
static_assert(std::is_same_v<T, int> || std::is_same_v<T, double>);
// ...
}
S<int> and S<double> (a.k.a. Di and Dd) are two different types.
Period.
It doesn't matter that they are template instantiations.
So, do what you'd normally do when you need a function to take an argument of one of two or more types:
make it take a variant, or
make it a template, or
write an overload
Related
I have a problem with inner classes in class templates. I have a template class (say: Matrix<T>), and a subclass (say: Matrix<T>::Row). Now I want to to write a function which operates on instances of the subclass (say: negate(Matrix<T>::Row &)). I tried to declare the function with template<class T> negate(typename Matrix<T>::Row &), but when I try to use it, the compiler tells me that it cannot find a match.
Here's an abstract example:
template<class T>
class A
{
public:
class B
{
};
};
template<class T>
void x(typename A<T>::B &)
{
}
int main()
{
A<int>::B b;
x(b); // doesn't work: Error: Could not find a match
// for x<T>(A<int>::B) needed in main().
x<int>(b); // works fine
}
Why does the compiler does not manage to find x in the first case? Is there a way to modify this that it works (without explicitly specifying the type int)?
(I also have similar problems where x is of the form template<class T, class S> void x(typename A<T>::B &, const S &);, whence I would really like not to be forced to explicitly name all types while doing the call.)
I have tried this with g++ 4.4.3, g++ 4.5.2, and Sun Studio 5.9, all give the same result. Thanks a lot in advance for anything helpful!
How should the compiler be able to deduce this? Imagine the following setup:
struct A { typedef int T; };
struct B { typedef int T; };
template <typename S> void foo(typename S::T);
Now when you say int x; foo(x);, there's no way to match this unambiguously.
The point is that you are not deducing a template parameter from a given class template, but rather just an arbitrary, free-standing type. The fact that that type was defined inside another class is not relevant for that.
That is non-deducible context. That is why the template argument cannot be deduced by the compiler.
Just imagine, you might have specialized A as follows:
template <>
struct A<SomeType>
{
typedef std::map <double, double> B;
};
Now this specialization has a nested type called B which is a typedef of std::map<double,double>.
So how would the compiler deduce the type SomeType, given that A<SomeType>::B is std::map<double, double>?
And in fact, there can be many such specializations, as such:
template <>
struct A<SomeOtherType>
{
typedef std::map <double, double> B;
};
Even this specialization has B as nested type.
Now if I say A<T>::B is std::map<double,double>, then can you say what T is? Is it SomeType? or SomeOtherType?
It would need to deduce the type T for the call to template function x, and template argument deduction is only allowed in a specific set of circumstances:
http://publib.boulder.ibm.com/infocenter/compbgpl/v9v111/index.jsp?topic=/com.ibm.xlcpp9.bg.doc/language_ref/template_argument_deduction.htm
A<T>::B
does not seem to be one of them :/
I am trying to write a class template that uses a parameter-pack and implements a member function for each type contained in the parameter-pack.
This is what I have so far:
template <typename...T>
class Myclass {
public:
void doSomething((Some_Operator_to_divorce?) T) {
/*
* Do Something
*/
std::cout << "I did something" << std::endl;
}
};
My goal is to have a class template that can be used in the following way:
Myclass<std::string, int, double> M;
M.doSomething("I am a String");
M.doSomething(1234);
M.doSomething(0.1234);
Where the class template mechanism will create an implementation for a doSomething(std::string x), a doSomething(int x) and a doSomething(double x) member function but not a doSomething(std::string x, int i, double f) member function.
I found a lot of examples in the web on the usability of parameter-packs, but I could not figure out if it can be used for my purpose, or if I totally misunderstood for what a parameter-pack can be used.
I thought that I need to unpack the parameter-pack but, after reading a lot of examples about unpacking parameter packs, I believe that this is not the right choice and it has a complete different meaning.
So, therefore, I am looking for a operation to "divorce" a parameter-pack.
There is no "operator" specifically that supports this, but what you're requesting can be done in a few different ways, depending on your requirements.
The only way to "extract" T types from a parameter pack of a class template with the purpose of implementing an overload-set of functions is to implement it using recursive inheritance, where each instance extracts one "T" type and implements the function, passing the rest on to the next implementation.
Something like:
// Extract first 'T', pass on 'Rest' to next type
template <typename T, typename...Rest>
class MyClassImpl : public MyClassImpl<Rest...>
{
public:
void doSomething(const T&) { ... }
using MyClassImpl<Rest...>::doSomething;
};
template <typename T>
class MyClassImpl<T> // end-case, no more 'Rest'
{
public:
void doSomething(const T&) { ... }
};
template <typename...Types>
class MyClass : public MyClassImpl<Types...>
{
public:
using MyClassImpl<Types...>::doSomething;
...
};
This will instantiate sizeof...(Types) class templates, where each one defines an overload for each T type.
This ensures that you get overload semantics -- such that passing an int can call a long overload, or will be ambiguous if there are two competing conversions.
However, if this is not necessary, then it'd be easier to enable the function with SFINAE using enable_if and a condition.
For exact comparisons, you could create an is_one_of trait that only ensures this exists if T is exactly one of the types. In C++17, this could be done with std::disjunction and std::is_same:
#include <type_traits>
// A trait to check that T is one of 'Types...'
template <typename T, typename...Types>
struct is_one_of : std::disjunction<std::is_same<T,Types>...>{};
Alternatively, you may want this to only work if it may work with convertible types -- which you might do something like:
template <typename T, typename...Types>
struct is_convertible_to_one_of : std::disjunction<std::is_convertible<T,Types>...>{};
The difference between the two is that if you passed a string literal to a MyClass<std::string>, it will work with the second option since it's convertible, but not the first option since it's exact. The deduced T type from the template will also be different, with the former being exactly one of Types..., and the latter being convertible (again, T may be const char*, but Types... may only contain std::string)
To work this together into your MyClass template, you just need to enable the condition with SFINAE using enable_if:
template <typename...Types>
class MyClass
{
public:
// only instantiates if 'T' is exactly one of 'Types...'
template <typename T, typename = std::enable_if_t<is_one_of<T, Types...>::value>>
void doSomething(const T&) { ... }
// or
// only instantiate if T is convertible to one of 'Types...'
template <typename T, typename = std::enable_if_t<is_convertible_to_one_of<T, Types...>::value>>
void doSomething(const T&) { ... }
};
Which solution works for you depends entirely on your requirements (overload semantics, exact calling convension, or conversion calling convension)
Edit: if you really wanted to get complex, you can also merge the two approaches... Make a type trait to determine what type would be called from an overload, and use this to construct a function template of a specific underlying type.
This is similar to how variant needs to be implemented, since it has a U constructor that considers all types as an overload set:
// create an overload set of all functions, and return a unique index for
// each return type
template <std::size_t I, typename...Types>
struct overload_set_impl;
template <std::size_t I, typename T0, typename...Types>
struct overload_set_impl<I,T0,Types...>
: overload_set_impl<I+1,Types...>
{
using overload_set_impl<I+1,Types...>::operator();
std::integral_constant<std::size_t,I> operator()(T0);
};
template <typename...Types>
struct overload_set : overload_set_impl<0,Types...> {};
// get the index that would be returned from invoking all overloads with a T
template <typename T, typename...Types>
struct index_of_overload : decltype(std::declval<overload_set<Types...>>()(std::declval<T>())){};
// Get the element from the above test
template <typename T, typename...Types>
struct constructible_overload
: std::tuple_element<index_of_overload<T, Types...>::value, std::tuple<Types...>>{};
template <typename T, typename...Types>
using constructible_overload_t
= typename constructible_overload<T, Types...>::type;
And then use this with the second approach of having a function template:
template <typename...Types>
class MyClass {
public:
// still accept any type that is convertible
template <typename T, typename = std::enable_if_t<is_convertible_to_one_of<T, Types...>::value>>
void doSomething(const T& v)
{
// converts to the specific overloaded type, and call it
using type = constructible_overload_t<T, Types...>;
doSomethingImpl<type>(v);
}
private:
template <typename T>
void doSomethingImpl(const T&) { ... }
This last approach does it two-phase; it uses the first SFINAE condition to ensure it can be converted, and then determines the appropriate type to treat it as and delegates it to the real (private) implementation.
This is much more complex, but can achieve the overload-like semantics without actually requiring recursive implementation in the type creating it.
let's say you have a class A (C++17):
template<class T>
struct A
{
A() = default;
A(T t) : val(t)
{
}
A operator*(A a)
{
return A(a.val * this->val);
}
T val;
};
However, 99% of the time the value-type of A is going to be an int, so you use a deduction guide to reduce the verbosity:
A()->A<int>;
So that's cool, now you can define variables without the template list:
A myVar;
The problem I'm having is that it seems to break down when it comes to function signatures, for example the following requires use of a template argument list:
auto ASquared = [](A a, A b) { return a * b; };
error C2955: 'A': use of class template requires template argument
list
When I wanted it to deduce that A was A<int>.
My question is: is this an inherent limitation, or am I just missing a different deduction guide that could make this syntax work?
The language doesn't allow this. Deduction doesn't take place within a function signature because there's nothing to deduce from.
Suppose we have this code:
template <class T, void (*u)(T&)>
void Foo()
{
// store the function u internally . . .
}
There are reasons to do something like this and I won't attempt to go into them. However, is there any way to avoid having to specify type T when calling Foo()? For example, to compile, one normally needs:
Foo<int, MyIntFunction>();
But if this int can be deduced from the function pointer, is this possible:
Foo<MyIntFunction>();
EDIT I'm aware of the solution to pass the actual function pointer in as a function parameter, however this is not desired here as it has some perf drawbacks in intensive loop.
In this example u is not a function pointer, it's a type (the signature of a function pointer). If you want to store a function pointer you need to pass it.
template<class T, class F = void(*)(T&)>
void Foo(F f)
{
// store the function pointer f here
}
called like so:
struct SomeType {};
void bar(SomeType& x);
Foo(&bar);
Is this what you mean to do?
Short answer: I don't think it is possible.
Long one.. When calling a template function, you cannot omit the first parameter and specify the second: the compiler would try to match your MyIntFunction to the template parameter T. Generally, you can specify the first, but omit the second if the compiler can infer the second template parameter. In this case, this is not an option however, because you want to specify the second parameter explicitly.
The second template parameter has a dependency (T) on the first template parameter. Therefore, reversing the order of the template parameters is also not an option.
Your best bet would be to define it in a way similar to what Richard suggested:
template<class T>
void Foo(T f)
{
int a(1);
f(a); // this forces f to be a function taking an int as parameter
}
Here is a dirty implementation which basically does what the OP was asking for. It depends on too many assumptions, but could be at least something to discuss. The idea is to specify in advance all possible types which can serve as function argument, and then deduce this type.
#include<iostream>
template<typename T>
struct TD; //type display
template<typename FunctionType, typename T, typename ... Ts>
struct ArgumentDeduction
{
typedef typename std::conditional<std::is_same<void, typename std::result_of<FunctionType(T)>::type>::value
, T
, typename ArgumentDeduction<FunctionType, Ts ...>::type
>::type type;
};
template<typename FunctionType, typename T>
struct ArgumentDeduction<FunctionType, T>
{
typedef typename std::conditional<std::is_same<void, typename std::result_of<FunctionType(T)>::type>::value
, T
, void
>::type type;
};
template<typename FunctionType
, typename T = typename ArgumentDeduction<FunctionType, int, double>::type >
void foo()
{
TD<T>();
}
struct AvoidConversion
{
struct DummyType{};
template<typename T> DummyType operator()(T x) { return DummyType(); }
};
struct Bar : public AvoidConversion
{
using AvoidConversion::operator();
void operator()(int x);
//void operator()(double x); //try also this
};
int main()
{
foo<Bar>(); //calls the foo<Bar,int> version
}
One main assumption here is the form of the Bar functor, which in principle accepts any type, but has a relevant implementation of type void only for the single allowed type.
Again, I don't think this is rather useful, but I guess this comes closest to the OP's question up to now.
DEMO
EDIT: Otherwise, i.e. without AvoidConversion in the code above, the compiler will perform an implicit conversion and the argument deduction gives true for all types which are convertible into each other (such that, e.g., int is deduced when there is only a function taking double).
If someone sees a way to avoid this ugly AvoidConversion hack and deduce the parameter type somehow more elegant, I would be interested in seeing that.
I want to somehow merge templates like these into one:
template <class Result, class T1, class T2>
class StupidAdd
{
public:
T1 _a; T2 _b;
StupidAdd(T1 a, T2 b):_a(a),_b(b) {}
Result operator()() { return _a+_b; }
};
template <class Result, class T1, class T2>
class StupidSub
{
public:
T1 _a; T2 _b;
StupidSub(T1 a, T2 b):_a(a),_b(b) {}
Result operator()() { return _a-_b; }
};
(followed by the same code for Mul, Div, etc) where all the code is the same,
except for the actual "+", "-" (and "StupidAdd", "StupidSub", etc).
These Stupid "functors" are then used by another template.
How can I avoid the repetition, WITHOUT the preprocessor?
(The reason I got into templates was to avoid the preprocessor)
That is, how can I pass arithmetic operators into a template?
Maybe you could use std::plus<T>, std::minus<T>, std::multiplies<T> and std::divides<T>. However, these will work only if both operands are of the same type, or probably if the left one can be converted to the type of the first one.
I don't see any way to achieve what you're trying to do, except by using the preprocessor. Any good reasons for not wanting macros ?
If you want to make sure the return type is large enough to contains the result, you could do something along this way:
#include <functional>
#include <boost/mpl/if_.hpp>
// Metafunction returning the largest type between T and U
// Might already exist in Boost but I can't find it right now...maybe
// boost::math::tools::promote_args
template <typename T, typename U>
struct largest :
boost::mpl::if_<
boost::mpl::bool_<(sizeof(T) > sizeof(U))>,
T,
U
>
{};
template <typename T, typename U, template <typename S> class Op>
struct Foo
{
typedef typename largest<T, U>::type largeType;
largeType bar(const T & t, const U & u)
{
return Op<largeType>()(t, u); // Applies operator+
}
};
int main()
{
Foo<int, double, std::plus> f;
double d = f.bar(12, 13.0); // takes int and double, returns double
}
Here, I used Boost MPL to write the largest metafunction, but you could write your own if metafunction if you cannot use Boost (class template parameterized by two types and a bool, specialized for true and false).
To determine the return type of an expression, you could also have a look at boost::result_of which, if I understand correctly, is equivalent to the upcoming decltype operator in C++0x.
Thanks Luc, this is very cool.
I finally did it in a simpler way:
#include <functional>
template <
class Result,
class T1,
class T2,
template <class ReturnType> class BinaryOp>
class Stupido
{
public:
T1 _a; T2 _b;
Stupido(T1 a, T2 b):_a(a),_b(b) {}
Result operator()() { return BinaryOp<Result>()((Result)_a,(Result)_b); }
};
And used the "plus", "minus" when instantiating Stupido.
The cast to "Result" was enough for my needs (int + double => double + double => double)
I think there's an improvement to OldCoder's solution:
#include <functional>
template <class Result,
template <class Result> class BinaryOp>
struct Stupido
{
template <typename T1, typename T2>
Result operator()(const T1& a, const T2& b) { return BinaryOp<Result>()((Result)a,(Result)b); }
};
This way the call can be made as:
Stupido<int, std::plus > stup;
int result = stup(3.0f, 2.0);
and the same function object can be used with multiple operands, so it could be passed in to a std::transform call.
I believe there must be a way to remove one Result from the template declaration, but I am unable to find it.
I'd use the C++ 0x decltype and the new definition of auto. You'll still need to define the classes, but using these, you can do a nicer job of defining them. They'll still be about as much work to define, but at least using them will be considerably cleaner. In particular, you can use decltype/auto to deduce the correct return type instead of having to specify it explicitly.
These are available with a fair number of recent compilers -- Intel C++, g++, Comeau, the beta of VC++ 2010, and even the most recent iteration of Borland/Inprise/Embarcadero/this week's new name.