My program generates random strings that have a "type" and an identifier. Like so:
float lHTY8Au8b9 = float();
int dO3PNUInH6 = int();
float B_MtShimak = float();
float hgi_TzaVEv = float();
double mfW8kr6h6q = double();
std::string lSLj9antfj = std::string();
char MQkeARWYTL = char();
char Oe7G_ZRJy6 = char();
float qUwmOWeilK = float();
double FJYIODwQfx = double();
Then I have the following to see if two arbitrary variables can be added:
template <typename A, typename B>
typename std::enable_if<std::is_convertible<A, B>::value, decltype(A() + B())>::type
try_to_add(A a, B b) {
return a + b;
}
Of course, it works because I get the following error:
main.cpp:51:54: error: no matching function for call to ‘try_to_add(double&, std::string&)’
try_to_add<double,std::string>(mfW8kr6h6q,lSLj9antfj);
However what I want instead is a list of candidates that don't cause a compile error. I can't hardcode the template parameters because it only accepts ints, and I cannot check inside the generator program because they're just strings, and attempting to use try_to_add with non-convertible types will cause a compile error. I know that SFINAE is the wrong approach, but is there a way to get try_to_add to simply do nothing, rather than generate a compile error?
Coliru
Add another overlaod with the inverse condition that does nothing.
template <typename A, typename B>
typename std::enable_if<!std::is_convertible<A, B>::value>::type
try_to_add(A, B) { }
Here is a few useful techniques. First, instead of is_convertible, we just try adding. if it works, bonus. Second, I use perfect forwarding.
Finally, I use a variardic pack for the "does work" catch-all. This is the sink technique.
#include <iostream>
#define RETURNS(X) ->decltype(X) { return (X); }
template<typename A, typename B>
auto try_to_add(A&& a, B&& b)
RETURNS( std::forward<A>(a) + std::forward<B>(b) )
template<typename... Ts>
void try_to_add( Ts&&... ) {
std::cout << "failed to add\n";
}
struct foo {};
int main() {
int a =1, b=2;
std::cout << try_to_add( a, b ) << "\n";
try_to_add( a, foo{} );
}
The RETURNS macro works around the lack of automatic return type deduction in C++11. In C++1y we will have a better option that lets us omit the repeated -> (X) { returns (X); } annoyance.
The point of the variardic args is that such a pack will only match if all overloads without the variardic args fail to match (they are considered last). This is useful because you don't have to maintain the bool condition in two different spots at once (once inverted).
The RETURNS macro can be expanded:
template<typename A, typename B>
auto try_to_add(A&& a, B&& b)
-> decltype( std::forward<A>(a) + std::forward<B>(b) )
{ return ( std::forward<A>(a) + std::forward<B>(b) ); }
if you prefer not to use macros (which is understandable).
Related
In a project I'm working on I have a templated function similar to this where all of the arguments should be of type T
#include <iostream>
template<typename T> bool aWithinBOfC(T a, T b, T c)
{
return std::abs(a - c) < b;
}
the issue I'm having is it won't compile if all of the arguments are not of the same type but it seems reasonable that it should implicitly cast similar types to the one with the highest resolution before evaluation. Is there any way to get a call like this to be valid?
int main()
{
double a{1.2};
double b{1.4};
float c{0.1f};
std::cout << aWithinBOfC(a, b, c) << std::endl;
}
Something along these lines, perhaps:
template<typename T>
bool aWithinBOfCImpl(T a, T b, T c) {
/* actual implemenattion */
}
template <typename ... Args>
auto aWithinBOfC(Args... args) {
return aWithinBOfCImpl<std::common_type_t<Args...>>(args...);
}
Demo
You don’t need implicit conversions at the call site. The compiler will implicitly convert the types to the largest one in the expression in the return statement.
template <class T, class U, class V>
bool aWithinBOfC(T a, U b, V c) {
return std::abs(a - c) < b;
}
I am new to C++ and currently trying to understand how template functions work. First I wanted to add two numerical values of the same type, which is quite easy to understand.
template <typename T>
T add(T a, T b){return a+b;}
int main(){
float a_f=2.5;float b_f=1.5;float c_f;
int a_i=2;int b_i=1;int c_i;
c_f = add(a_f, b_f);
c_i = add(a_i, b_i);
return 0;
}
Next I wanted to add two numerical numbers with different and equal types. My naive assumption was this:
template<typename R, typename S, typename T>
R add(S a, T b){return a+b;}
int main(){
float a=3.2; int b=2;
auto result1 = add(a,b); // error: no matching function for call to ‘add(float&, int&)’
auto result2 = add(a,a); // error: no matching function for call to ‘add(float&, float&)’
auto result3 = add(b,b); // error: no matching function for call to ‘add(int&, int&)’
return 0;
}
I am aware that this approach is not correct, because the typename's share an intersection regarding data types and therefore the declaration itself cannot be correct.
How could a simple add() function be implemented that adds two numeric values together, regardless of type?
The problem is not with an intersection, but that it cant deduce R. In
template<typename R, typename S, typename T>
R add(S a, T b){return a+b;}
There is nothing telling the compiler what R should be. It's not deduced from the variable you are assigning the result to and you do not specify it, so there is no valid call that it can do. To fix this you can just get rid of R and use the auto return type to have it deduced for you like
template<typename S, typename T>
auto add(S a, T b){return a+b;}
How could a simple add() function be implemented that adds two numeric values together, regardless of type?
In C++14:
template<class T, class U>
auto add(T t, U u) {
return t + u;
}
In the above, the type of the return value is deduced from the type of expression t + u.
C++11 doesn't deduce return types but allows for trailing return type, so a C++11 version is:
template<class T, class U>
auto add(T t, U u) -> decltype(t + u) {
return t + u;
}
What you want is to deduce the return type. However, type deduction for type template parameter only apply for function parameter.
Even though typenames are not the right tool to do that, C++ offers other mean to deduce the type.
Use auto
You can simply put auto there and let the compiler deduce from the return type:
template<typename S, typename T>
auto add(S a, T b){ return a + b; }
Use trailing return types
You can also use the trailing return type if you want to be more explicit on the return type of the function:
template<typename S, typename T>
auto add(S a, T b) -> decltype(a + b) { return a + b; }
Suppose I have code like this:
void f(int a = 0, int b = 0, int c = 0)
{
//...Some Code...
}
As you can evidently see above with my code, the parameters a,b, and c have default parameter values of 0. Now take a look at my main function below:
int main()
{
//Here are 4 ways of calling the above function:
int a = 2;
int b = 3;
int c = -1;
f(a, b, c);
f(a, b);
f(a);
f();
//note the above parameters could be changed for the other variables
//as well.
}
Now I know that I can't just skip a parameter, and let it have the default value, because that value would evaluate as the parameter at that position. What I mean is, that I cannot, say call, f(a,c), because, c would be evaluated as b, which is what I don't want, especially if c is the wrong type. Is there a way for the calling function to specify in C++, to use whatever default parameter value there is for the function in any given position, without being limited to going backwards from the last parameter to none? Is there any reserved keyword to achieve this, or at least a work-around? An example I can give would be like:
f(a, def, c) //Where def would mean default.
There isn't a reserved word for this, and f(a,,c) is not valid either. You can omit a number of rightmost optional parameters, as you show, but not the middle one like that.
http://www.learncpp.com/cpp-tutorial/77-default-parameters/
Quoting directly from the link above:
Multiple default parameters
A function can have multiple default parameters:
void printValues(int x=10, int y=20, int z=30)
{
std::cout << "Values: " << x << " " << y << " " << z << '\n';
}
Given the following function calls:
printValues(1, 2, 3);
printValues(1, 2);
printValues(1);
printValues();
The following output is produced:
Values: 1 2 3
Values: 1 2 30
Values: 1 20 30
Values: 10 20 30
Note that it is impossible to supply a user-defined value for z
without also supplying a value for x and y. This is because C++ does
not support a function call syntax such as printValues(,,3). This has
two major consequences:
1) All default parameters must be the rightmost parameters. The
following is not allowed:
void printValue(int x=10, int y); // not allowed
2) If more than one default parameter exists, the leftmost default
parameter should be the one most likely to be explicitly set by the
user.
As workaround, you may (ab)use boost::optional (until std::optional from c++17):
void f(boost::optional<int> oa = boost::none,
boost::optional<int> ob = boost::none,
boost::optional<int> oc = boost::none)
{
int a = oa.value_or(0); // Real default value go here
int b = ob.value_or(0); // Real default value go here
int c = oc.value_or(0); // Real default value go here
//...Some Code...
}
and then call it
f(a, boost::none, c);
Not exactly what you asked for, but you can use std::bind() to fix a value for a parameter.
Something like
#include <functional>
void f(int a = 0, int b = 0, int c = 0)
{
//...Some Code...
}
int main()
{
// Here are 4 ways of calling the above function:
int a = 2;
int b = 3;
int c = -1;
f(a, b, c);
f(a, b);
f(a);
f();
// note the above parameters could be changed
// for the other variables as well.
using namespace std::placeholders; // for _1, _2
auto f1 = std::bind(f, _1, 0, _2);
f1(a, c); // call f(a, 0, c);
return 0;
}
With std::bind() you can fix values different from default parameters' values or values for parameters without default values.
Take into account that std::bind() is available only from C++11.
You already have an accepted answer, but here's another workaround (that - I believe - has advantages over the other proposed workarounds):
You can strong-type the arguments:
struct A { int value = 0; };
struct B { int value = 2; };
struct C { int value = 4; };
void f(A a = {}, B b = {}, C c = {}) {}
void f(A a, C c) {}
int main()
{
auto a = 0;
auto b = -5;
auto c = 1;
f(a, b, c);
f(a, C{2});
f({}, {}, 3);
}
Advantages:
it's simple and easy to maintain (one line per argument).
provides a natural point for constricting the API further (for example, "throw if B's value is negative").
it doesn't get in the way (works with default construction, works with intellisense/auto-complete/whatever as good as any other class)
it is self-documenting.
it's as fast as the native version.
Disadvantages:
increases name pollution (better put all this in a namespace).
while simple, it is still more code to maintain (than just defining the function directly).
it may raise a few eyebrows (consider adding a comment on why strong-typing is needed)
If all parameters of the function were of distinct types, you could find out which parameters were passed and which were not and choose the default value for the latter.
In order to achieve the distinct type requirement, you can wrap your parameters and pass it to a variadic function template.
Then even the order of the argument does not matter anymore:
#include <tuple>
#include <iostream>
#include <type_traits>
// -----
// from http://stackoverflow.com/a/25958302/678093
template <typename T, typename Tuple>
struct has_type;
template <typename T>
struct has_type<T, std::tuple<>> : std::false_type {};
template <typename T, typename U, typename... Ts>
struct has_type<T, std::tuple<U, Ts...>> : has_type<T, std::tuple<Ts...>> {};
template <typename T, typename... Ts>
struct has_type<T, std::tuple<T, Ts...>> : std::true_type {};
template <typename T, typename Tuple>
using tuple_contains_type = typename has_type<T, Tuple>::type;
//------
template <typename Tag, typename T, T def>
struct Value{
Value() : v(def){}
Value(T v) : v(v){}
T v;
};
using A = Value<struct A_, int, 1>;
using B = Value<struct B_, int, 2>;
using C = Value<struct C_, int, 3>;
template <typename T, typename Tuple>
std::enable_if_t<tuple_contains_type<T, Tuple>::value, T> getValueOrDefaultImpl(Tuple t)
{
return std::get<T>(t);
}
template <typename T, typename Tuple>
std::enable_if_t<!tuple_contains_type<T, Tuple>::value, T> getValueOrDefaultImpl(Tuple)
{
return T{};
}
template <typename InputTuple, typename... Params>
auto getValueOrDefault(std::tuple<Params...>, InputTuple t)
{
return std::make_tuple(getValueOrDefaultImpl<Params>(t)...);
}
template <typename... Params, typename ArgTuple>
auto getParams(ArgTuple argTuple)
{
using ParamTuple = std::tuple<Params...>;
ParamTuple allValues = getValueOrDefault(ParamTuple{}, argTuple);
return allValues;
}
template <typename... Args>
void f(Args ... args)
{
auto allParams = getParams<A,B,C>(std::make_tuple(args...));
std::cout << "a = " << std::get<A>(allParams).v << " b = " << std::get<B>(allParams).v << " c = " << std::get<C>(allParams).v << std::endl;
}
int main()
{
A a{10};
B b{100};
C c{1000};
f(a, b, c);
f(b, c, a);
f(a, b);
f(a);
f();
}
output
a = 10 b = 100 c = 1000
a = 10 b = 100 c = 1000
a = 10 b = 100 c = 3
a = 10 b = 2 c = 3
a = 1 b = 2 c = 3
live example
I will just use static functions to define default values that can change:
class defValsExample
{
public:
defValsExample() {
}
static int f1def_a() { return 1; }
static int f1def_b() { return 2; }
int f1(int a = f1def_a(), int b = f1def_b()) {
return a+b;
}
};
int main()
{
defValsExample t;
int c = t.f1(t.f1def_a(),4);
}
I come from a Swift background and, though I know some C as well, this is my first time writing C++ code.
In Swift it is possible to write a function that takes any number of arguments:
func foo(bar: String...) {
// ...
}
and bar can be of any type (String, Bool, Struct, Enum, etc).
I was wondering if the same can be done in C++. So, ideally I would write:
struct X {
string s;
X(int);
// ...
}
void foo(string s, ...) {
// ...
}
foo("mystr", X(1), X(2), X(3));
and inside foo I would somehow be able to access the list of arguments, somewhat akin to a printf function.
Right now I'm using a vector<X> as argument, since all the arguments have type X. However, that makes calling foo somewhat ugly, in my opinion:
foo("mystr", { X(1), X(2), X(3) });
Any solution I'm not seeing due to my strong lack of knowledge towards C++?
Edit:
This is what I want done specifically inside foo:
string ssub(string s, vector<X> v) {
int index, i = 0;
while (1) {
index = (int)s.find(SUB);
if (index == string::npos) { break; }
s.erase(index, string(SUB).size());
s.insert(index, v[i].tostr());
i++;
}
return s;
}
Basically, as long as I'm given a way to sequentially access the arguments, all is good.
Here's one of many ways.
You can copy/paste this entire program into your IDE/editor.
#include <utility>
#include <iostream>
#include <typeinfo>
#include <string>
//
// define a template function which applies the unary function object func
// to each element in the parameter pack elems.
// #pre func(std::forward<Elements>(elems)) must be well formed for each elems
// #returns void
//
template<class Function, class...Elements>
auto do_for_all(Function&& func, Elements&&...elems)
{
using expand = int[];
void(expand { 0, (func(elems), 0)... });
}
// a test structure which auto-initialises all members
struct X
{
int i = 0;
std::string s = "hello";
double d = 4.4;
};
//
// The function foo
// introduces itself by writing intro to the console
// then performs the function object action on each of args
// #note all arguments are perfectly forwarded - no arguments are copied
//
template<class...Args>
auto foo(const std::string& intro, Args&&...args)
{
std::cout << "introducing : " << intro << std::endl;
auto action = [](auto&& arg)
{
std::cout << "performing action on: " << arg
<< " which is of type " << typeid(arg).name() << std::endl;
};
do_for_all(action, std::forward<Args>(args)...);
}
int main()
{
// make an X
auto x = X(); // make an X
// foo it with the intro "my X"
foo("my X", x.i, x.s, x.d);
}
example output:
introducing : my X
performing action on: 0 which is of type i
performing action on: hello which is of type NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
performing action on: 4.4 which is of type d
You can use variadic templates (since C++11):
template <typename ... Type>
void foo(Type& ... args) {
// do whatever you want, but this may be tricky
}
foo(X(1), X(2), X(3));
Example of variadic templates: min function
This is the code I wrote to get rid of ugly calls to std::min when calculating minimum of many values.
#include <type_traits>
namespace my {
template <typename A, typename B>
auto min(const A& a, const B& b) -> typename std::common_type<A, B>::type {
return (a<b)?a:b;
}
template <typename A, typename B, typename ... T >
auto min(const A& a, const B& b, const T& ... c) -> typename std::common_type<A, B, T ...>::type {
const typename std::common_type<A, B, T ...>::type tmp = my::min(b, c ...);
return (a<tmp)?a:tmp;
}
}
// calculating minimum with my::min
my::min(3, 2, 3, 5, 23, 98);
// doing the same with std::min
std::min(3, std::min(2, std::min(3, std::min(5, std::min(23, 98))))); // ugh, this is ugly!
Here's the tricky part: you can't cycle through the parameter pack like you do with vectors. You'll have to do some recursion as shown in the example.
You could write a variadic template function, pass the arguments into some std::initializer_list and iterate over the list, for example:
#include <initializer_list>
template <typename ... Args>
void foo(Args && ... args) {
std::initializer_list<X> as{std::forward<Args>(args)...};
for (auto const & x : as)
// Use x here
}
int main() {
foo(1, 2, 3, 4, 5);
}
Note also, that you might want to change the argument list and type of the initializer list to meet your exact use-case. E.g. use Args * ... args and std::initializer_list<X *> or similar.
I'm trying to make variadic template function, which takes as arguments overloaded function and its arguments :)
int sumall(int a) { return a; }
int sumall(int a, int b) { return a+b; }
template<typename R, typename... A>
R doit( R(*f)(A...), A... a) {
return f(a...); }
I want to call doit without any template specifiers nor casting:
cout << doit(sumall, 7, 6) << endl
That doesn't compile, but when return types are void, everything work perfect:
void printsum(int a) { cout << a << endl; }
void printsum(int a, int b) { cout << a+b << endl; }
template<typename... A>
void vdoit( void(*f)(A...), A... a) {
f(a...); }
// ...
vdoit(printsum, 7, 6);
Is it possible to modify first template to work with modyfing only doit template (I want to preserve sumall functions and doit call)? I think it can be done with removing typename R and leaving just template<typename... A> since R depends on A... and f, but I don't have any idea how to show that dependency.
When taking a pointer of a function the compiler needs to know which of the overloads you want to use. There is no way to pass a pointer to an "overload set" and have the compiler decide later. Neither of you examples works with any of the compilers I tried (very recent versions of EDG, gcc, and clang).
I don't think you can do what you want without changing the notation of your call. If you are willing to change the call you can encapsulate the knowledge about the function to be called into a class, e.g.:
struct sumall_t {
template <typename... T>
auto operator()(T... args) -> decltype(sumall(args...)) {
return sumall(args...);
}
};
This effectively creates a wrapper for an overload set. Since the result type can't be deduced directly and may depend on how the function is called, you'd need to use a different version of doit() as well:
template<typename Func, typename... A>
auto doit( Func f, A... a) ->decltype(f(a...)) {
return f(a...);
}
This would then be used something like this:
doit(sumall_t(), 1, 2);
Another way to fix this is to mandate specification of the result type: in some way you try to do two things at once: you want to deduce the result type of the function to be called and you want to guide the compiler to choose a specific overload of a result set. However, these are interdependent. If you remove any dependency on deducing any template from the function pointer, you don't need wrap the overload set because you can determine the choice of overloaded function from the first argument to the function. In case you claim that "my compiler can do it if the return type isn't void" I'd say that your compiler is actually wrong in doing this.
(If you're prepared to use variadic macros, then scroll to the end of this answer to see a better answer which make everything fully variadic. But I think that variadic macros are just a g++ extension.)
It can be made to work, if you're prepared to put the name of the function at the end of the parameter list. By putting it later, the compiler can deduce the necessary types from the earlier parameters to doit:
cout << doit(7, 6, sumall) << endl;
cout << doit(10, sumall) << endl;
Here is a demo on ideone.
The downside is that you have to implement one doit for each number of parameters. I've only implemented it for one- and two- parameter functions, but it shouldn't be a problem to extend this:
int sumall(int a) { return a; }
int sumall(int a, int b) { return a+b; }
template<typename A1, typename A2, typename R>
auto doit( A1 a1, A2 a2, R (*f) (A1,A2)) -> R {
return f(a1, a2);
}
template<typename A1, typename R>
auto doit( A1 a1, R (*f) (A1)) -> R {
return f(a1);
}
Update: Sometimes, it might appear that you can get away with having f as the first argument. But that's not as robust as putting it at the end. Consider the example where where are two functions that take the same number of arguments, but different types of parameters. e.g.:
int sumall(int a, int b) { return a+b; }
string sumall(string a, string b) { return a+" "+b; }
You need to have the function as the last argument, in order that the template deduction can use the type and number of parameters at the start to deduce the types of the arguments. Here's a demo on ideone of function-arg first and function-arg last.
The only downside with putting the arg at the end is that we can't then use variadic templates - variadic arg packs must be at the end. And you must get the types exactly right - see how I had to use string("hi") instead of simply "hi".
Using variadic macros to have the best of all worlds
By implementing doit as a macro, and using variadic macros (a gcc/g++ extension), it is possible to have a fully variadic solution with the function name appearing first. A demo on ideone.
cout << doit(sumall, 7, 6) << endl;
cout << doit(sumall, 10) << endl;
cout << doit(sumall, string("hi"), string("world")) << endl;
By using decltype and a couple of other simple classes, we can use the args provided to deduce the types of the args and then it can use that to select the right method from the overload set and deduce the return type from that.
template<typename ...Args>
struct OverloadResolved {
template<typename R>
static auto static_doit( R (*f) (Args...), Args ... args ) -> R {
return f(args...);
}
};
template<typename ...Args>
auto deduce(Args...) -> OverloadResolved<Args...> {
return OverloadResolved<Args...>();
}
template<typename T>
struct dummy : public T { };
#define doit(f, ...) ( dummy<decltype(deduce( __VA_ARGS__ ))> :: static_doit(f, __VA_ARGS__) )
I'm pretty sure this is a safe use of macros, nothing will be evaluated twice (nothing inside decltype actually executes.