Pattern-matching inside a template constraint - d

This question is based on Andrei's answer to my question on signature constraints.
struct S(int x, int y) {
void fun(T)(T t) if (is(T U == S!(a, b), int a, int b)) { }
}
template s(int a, int b) {
enum result = S!(a,b)();
alias result s;
}
void main() {
auto s1 = S!(1, 1)();
auto s2 = S!(2, 2)();
auto s3 = s!(3, 3);
auto s4 = s!(4, 4);
s1.fun(s1); // ok
s1.fun(s2); // ok
s1.fun(s3); // compile error
s3.fun(s1); // ok
s3.fun(s3); // compile error
s3.fun(s4); // compile error
}
I don't understand why the code is producing compile errors. Any ideas?

First, I wouldn't recommend using a naked template to generate an instance of an object/struct, because you're essentially requiring the object to be CTFE-able. If you need an instance your best option is to return it from a templated function:
#property S!(a, b) s(int a, int b)()
{
return S!(a, b)();
}
However this still doesn't seem to work with the template constraint. I think this has to be a front-end bug. From what I can tell it seems that the type returned cannot be properly checked in the is() expression unless it was already instantiated somewhere else, e.g.:
struct S(int x, int y)
{
void fun(T)(T t)
if (is(T U == S!(a, b), int a, int b))
{
}
}
#property S!(a, b) s(int a, int b)()
{
return S!(a, b)();
}
void main()
{
auto s1 = S!(1, 1)();
auto s2 = S!(2, 2)(); // comment out and you get errors in fun() call
auto s3 = s!(2, 2);
s1.fun(s3);
}
I'll file this as a bug.
Edit: Filed as Issue 8493.

Related

Convert a function pointer to another having more arguments

Suppose I am trying to use a function which accepts a binary function and calls it with some arguments:
typedef double (*BinaryFunction)(double a, double b);
typedef double (*UnaryFunction)(double a);
// Can't change this
double ExternalFunction(BinaryFunction binaryFunction)
{
return binaryFunction(1, 2);
}
Now suppose a user of my code is going to provide me with a unary function. My goal is to convert it into a binary function so that I can call ExternalFunction with it:
double MyFunction(UnaryFunction unaryFunction)
{
BinaryFunction binaryFunction = /* want a function (a, b) -> unaryFunction(a + b) */;
return ExternalFunction(binaryFunction);
}
How do I do this? Just to be clear, I understand that this would be easy if the unary function were known at compile time, but it's not - it will be an argument to my function. Thanks in advance.
Here's a summary of my attempts. I believe I understand why these don't work, but I'm providing them so you can see what I've been thinking so far.
I can't use a lambda, because I'd have to capture UnaryFunction, and capturing lambdas can't be converted to function pointers:
double MyFunction(UnaryFunction unaryFunction)
{
BinaryFunction binaryFunction = [unaryFunction](double a, double b){ return unaryFunction(a + b); };
return ExternalFunction(binaryFunction);
}
Use std::function ? Can't get that to work either:
void MyFunction(UnaryFunction unaryFunction)
{
std::function<double(double, double)> binaryFunctionTemp = [unaryFunction](double a, double b)
{
return unaryFunction(a + b);
};
BinaryFunction binaryFunction = binaryFunctionTemp.target<double(double, double)>();
ExternalFunction(binaryFunction);
}
What about a function object? Won't work because we'd need a pointer to a member function:
class BinaryFromUnary
{
public:
BinaryFromUnary(UnaryFunction unaryFunction) : unary_(unaryFunction) {};
double operator()(double a, double b)
{
return unary_(a + b);
}
private:
UnaryFunction unary_;
};
void MyFunction(UnaryFunction unaryFunction)
{
BinaryFromUnary functionObject(unaryFunction);
std::function<double(double, double)> binaryFunction = functionObject;
ExternalFunction(binaryFunction.target<double(double, double)>());
}
Even had a go with std::bind (and probably messed it up):
struct Converter {
Converter(UnaryFunction unary) : unary_(unary) {}
double binary(double a, double b) const { return unary_(a + b); }
UnaryFunction unary_;
};
void MyFunction(UnaryFunction unaryFunction)
{
Converter converter(unaryFunction);
std::function<double(double, double)> binaryFunction = std::bind( &Converter::binary, converter, _1, _2);
ExternalFunction(binaryFunction.target<double(double, double)>());
}
Tried a couple of other things along the same lines. Any ideas would be much appreciated.
Use an external variable to hold the unary function.
Include standard disclaimers about how inelegant and non-thread safe this is, etc. but at least this is a hack consistent with the stated requirements:
#include <iostream>
typedef double (*BinaryFunction)(double a, double b);
typedef double (*UnaryFunction)(double a);
// Can't change this
double ExternalFunction(BinaryFunction binaryFunction) {
return binaryFunction(1, 2);
}
namespace foo {
thread_local UnaryFunction unaryFunction;
}
double MyBinaryFunction(double a, double b) {
return foo::unaryFunction(a + b);
}
double MyUnaryFunction(double a) {
return 2 * a;
}
double MyFunction(UnaryFunction unaryFunction) {
foo::unaryFunction = unaryFunction;
BinaryFunction binaryFunction = MyBinaryFunction;
return ExternalFunction(binaryFunction);
}
int main() {
std::cout << MyFunction(MyUnaryFunction) << std::endl; // 6
return 0;
}
I don't know your exact use-case, but there's a chance this might help you:
typedef double (*BinaryFunction)(double a, double b);
typedef double (*UnaryFunction)(double a);
// Can't change this
double ExternalFunction(BinaryFunction binaryFunction)
{
return binaryFunction(1, 2);
}
// If you always know the unary function at compile time:
// Create a wrapper function with the BinaryFunction signature that takes
// a unary function as a NTTP:
template <UnaryFunction unaryFunction>
double wrapper(double a, double b)
{
return unaryFunction(a + b);
}
// Simply use this wrapper to implement MyFunction as follows:
template <UnaryFunction unaryFunction>
double MyFunction()
{
return ExternalFunction(wrapper<unaryFunction>);
}
// Using it:
double unary1(double x) { return x * 2; }
double unary2(double x) { return x * 3; }
int main()
{
std::cout << MyFunction<unary1>() << '\n';
std::cout << MyFunction<unary2>() << '\n';
}
Have a godbolt link to play around with it as well.
Unlike the other answer, this doesn't require a global, but this also only works if you always know your function at compile-time, which there's a good chance you don't, so sorry in advance. Hope it was still interesting.

C++ Is there any guarantee that literals conditions generated by a template will be optimized away?

Excuse any mistakes in my code, I'm still learning C++ syntax. My question is not about whether the code is correct but whether a literal expression will be optimized away.
Let's say I have a function generated from a non-type template like this:
template <bool add>
int addIt(int a, int b) {
if (add) {
return a + b;
} else {
return a - b;
}
}
int v = addIt<true>(10, 5);
From my understanding, the compiler should expand the template to:
int addIt_someID(int a, int b) {
if (true) {
return a + b;
} else {
return a - b;
}
}
int v = addIt_someID(10, 5);
But since it now says if (true) it should be able to remove that entire branch, resulting in this:
void addIt_someID(int a, int b) {
return a + b;
}
int v = addIt_someID(10, 5);
This should be standard compiler behavior... but is this behavior well enough established that I can be certain of it from all major compilers?
I'm relying upon this behavior for a transpiler, and if it's not guaranteed I will have to implement it myself... if it is guaranteed I can let the C++ compiler to do it and that will save me a lot of time in having to parse and evaluate this myself.
This is never guaranteed for regular if (although I would say chaneces are pretty high). There are two ways to be sure. Simpler one requires C++17 (btw addIt seems to return wrong type):
template <bool add>
int addIt(int a, int b) {
if constexpr (add) {
return a + b;
} else {
return a - b;
}
}
int v = addIt<true>(10, 5);
if constexpr guerantees that this will be evaluated in compile time.
Another option is using template metaprogramming/explicit template specialization. For your code this would be pretty simple:
template <bool add>
int addIt(int a, int b);
template<> int addIt<true>(int a, int b) { return a + b; }
template<> int addIt<false>(int a, int b) { return a - b; }
int v = addIt<true>(10, 5);
For other cases you would need some more work like using std::enable_if and stuff like this

boost::polycollection, std::variant, or CRTP?

Suppose the "standard" C++ inheritance paradigm:
struct GeneralFunc
{
/*..members..*/
virtual double value(double a, double b) { return 0; }
};
struct Func_classA : GeneralFunc
{
/*..members..*/
double value(double a, double b) { return a * b; }
};
struct Func_classB : GeneralFunc
{
/*..members..*/
double value(double a, double b) { return a + b; }
};
void main(){
double a = 1.0, b = 1.0;
std::vector<GeneralFunc*> my_functions;
//fill my_functions from input
for (auto& f : my_functions)
{
double v = f->value(a, b);
}
}
I would like an implementation that is most efficient for the iteration, i.e. minimizes indirect references, maximizes inline optimizations, ect. To constrain the problem, I know beforehand each specific "type" I want to implement (I can define only the "func" types I require, without having to allow other possibilities).
several options appear available:
boost::polycollection
#include <boost/poly_collection/base_collection.hpp>
//...rest the same
boost::base_collection<GeneralFunc> my_functions
//...rest the same
std::variant
#include <variant>
//...rts
using funcs = std::variant<Func_classA, Func_classB /*..possibly more../*>
std::vector<funcs> my_functions
or CRTP (Curiously Recurring Template Pattern)
Let me know the correct nomenclature for this, but here I "upcast" the base class based on the "type" -- a kind of manual dispatch.
template<typename T>
struct GeneralFunc
{
/*..members..*/
int my_type;
double value(double a, double b) {
switch (my_type){
case TYPE_A:
return static_cast<Func_classA*>(this)->value(a,b);
/*..you get the idea..*/
I'm okay sacrificing marginal efficiency for ease of development, but is there a consensus on the "best practice" in this case?
EDITS* fixed some typos; my current development is "in-development" of CRTP the last option.
SOLUTION:
After testing, both boost::polycollection and std::variant are valid approaches. However, this turned out to be far most efficient (from memory, may be slightly off).
enum ftype { A = 0, B, C };
struct GeneralFunc
{
ftype my_type;
GeneralFunc(ftype t) : my_type(t) {}
inline double value(double a, double b) const; // delay definition until derived classes are defined
}
struct Func_classA : GeneralFunc
{
Func_classA() : GeneralFunc(ftype::A) {}
inline double value(double a, double b) const { return a * b; }
}
/* define B, C (& whatever) */
inline double GeneralFunc::value(double a, double b)
{
switch(my_type){
case (ftype::A):
return static_cast<Func_classA*>(this)->value(a,b);
/* same pattern for B, C, ect */
}
}
void main(){
std::vector<std::unique_ptr<GeneralFunc>> funcs;
funcs.push_back(std::make_unique<Func_classA>());
funcs.push_back(std::make_unique<Func_classB>());
funcs[0]->value(1.0,1.0); // calls Func_classA.value
funcs[1]->value(1.0,1.0); // calls Func_classB.value
}
I'd be tempted to just use std::function as the container, rather than re-writing it.
using GeneralFunc = std::function<double(double, double);
struct Func_classA
{
/*..members..*/
double value(double a, double b) { return a * b; }
/*explicit*/ operator GeneralFunc () const { return [this](double a, double b){ value(a, b) }; }
};
struct Func_classB
{
/*..members..*/
double value(double a, double b) { return a + b; }
/*explicit*/ operator GeneralFunc () const { return [this](double a, double b){ value(a, b) }; }
};
void main(){
double a = 1.0, b = 1.0;
std::vector<GeneralFunc> my_functions;
//fill my_functions from input
for (auto& f : my_functions)
{
double v = f(a, b);
}
}
I think there's an option you didn't include (which is the one I'd use for performance critical code), that is to create a tuple of function objects and "iterate" over such tuple. Unfortunately there is no nice API to iterate over a tuple, so one has to implement his own. See the snippet below
#include <tuple>
#include <functional>
template<int ... Id, typename Functions>
auto apply(std::integer_sequence<int, Id ...>, Functions& my_functions, double& v, double a, double b){
([](auto a, auto b){a=b;}(v, std::get<Id>(my_functions)( a, b )), ...);
}
int main(){
auto fA = [](double a, double b){return a*b;};
auto fB = [](double a, double b){return a+b;};
//create the tuple
auto my_functions=std::make_tuple(fA, fB);
double v=0;
double a = 1.;
double b = 1.;
//iterate over the tuple
apply(std::make_integer_sequence<int, 2>(), my_functions, v, a, b);
}
This way you create a type safe zero overhead abstraction, since the compiler knows everything about the types you use (you don't need any type erasure mechanism). Also there's no need of virtual functions (same as in CRTP), so the compiler will probably inline the function calls. The snippet above uses C++17 generic lambdas, could be also implemented in C++14 or C++11 compliant way, but it would be more verbose. I would prefer this over CRTP because to me it looks more readable: no static cast to the derived class, and no artificial hierarchy of inheritance.
EDIT: from your answer looks like you don't really need the CRTP here, what you write using the CRTP solution is equivalent to this
enum ftype { A = 0, B, C };
auto fA = [](double a, double b){return a*b;};
auto fB = [](double a, double b){return a+b;};
int main(){
std::vector<ftype> types(2);
types[0]=A;
types[1]=B;
auto value = [&types](double a, double b, ftype i){
switch(i){
case (ftype::A):
return fA(a,b);
break;
case (ftype::B):
return fB(a,b);
break;
}
};
double v=value(1., 1., A);
v=value(1., 1., B);
}
Might be a matter of taste, but I think the version above is more readable (you don't really need a common base class, or static cast to the derived class).

Passing value in factory pattern

I am learning factory design pattern. I am not able to figure out how we can pass parameters to object created using Factory pattern.
One Small Silly Example:
Suppose I have three class, Class A and class B and Class Number. Number being the base class. Also, class A expects three integers and has functionality to add them and class B expects two integer and adds them
Code Snippet:
int main()
{
Factory *facObj = new Factory();
// Addition for Two Integers
Number * numberObjOne = facObj->createObj("AddThreeInteger");
Number * numberObjTwo = facObj->createObj("AddTwoInteger");
}
Factory.cpp
Number * Factory::createObj(string str)
{
if (str == "AddThreeInteger")
{
return new A(1,2,3);
}
else if (str == "AddTwoInteger")
{
return new B(1,2);
}
else
return NULL;
}
Question: Now no matter what I do I can only add the hard coded numbers. How do I pass these integers value from my Client code or from main(). Its a silly example and I am new to programming. Kindly help me here. How can I not hardcode the value and get the results. Can I somwhow pass the values at facObj->createObj Am I making sense? Kindly help me.
Complete, runnable example. c++11 or better.
Note the use of unique_ptr. Don't use raw pointers.
#include <iostream>
#include <memory>
#include <stdexcept>
#include <exception>
#include <utility>
template<class T, class...Args>
struct creatable_from {
template<class X, class...Ys>
static auto test(int) -> decltype(X(std::declval<Ys>()...), void(), std::true_type());
template<class X, class...Ys>
static auto test(...) -> decltype(std::false_type());
static constexpr auto value = decltype(test<T, Args...>(0))::value;
};
struct Operation {
virtual ~Operation() = default;
virtual int operator()() const = 0;
};
struct Add : Operation
{
Add(int x, int y)
: x(x), y(y)
{}
int operator()() const override {
return x + y;
}
int x, y;
};
struct Sub : Operation
{
Sub(int x, int y)
: x(x), y(y)
{}
int operator()() const override {
return x - y;
}
int x, y;
};
struct AddSub : Operation
{
AddSub(int x, int y, int z)
: x(x), y(y), z(z)
{}
int operator()() const override {
return x + y - z;
}
int x, y, z;
};
struct Factory
{
template<class...Args>
std::unique_ptr<Operation> create(const std::string& type, Args&&...args)
{
if (type == "Add") {
return do_create<Add>(std::forward<Args>(args)...);
}
if (type == "Sub") {
return do_create<Sub>(std::forward<Args>(args)...);
}
if (type == "AddSub") {
return do_create<AddSub>(std::forward<Args>(args)...);
}
// default - return a null pointer, but would probably be better to
// throw a logic_error
return {};
}
private:
template<class T, class...Args>
static auto do_create(Args&&...args)
-> std::enable_if_t< creatable_from<T, Args...>::value, std::unique_ptr<T> >
{
return std::make_unique<T>(std::forward<Args>(args)...);
}
template<class T, class...Args>
static auto do_create(Args&&...args)
-> std::enable_if_t< not creatable_from<T, Args...>::value, std::unique_ptr<T> >
{
throw std::invalid_argument("wrong number of arguments");
}
};
int main()
{
auto facObj = Factory();
auto t1 = facObj.create("Add", 2, 3);
auto t2 = facObj.create("Sub", 3, 2);
auto t3 = facObj.create("AddSub", 2, 3, 4);
std::cout << (*t1)() << std::endl;
std::cout << (*t2)() << std::endl;
std::cout << (*t3)() << std::endl;
}
expected output:
5
1
1
There are many ways to do it.
One way is to have separate create methods in your factory, to construct each one of your subclasses. Each create method would take the appropriate parameters for the subclass it constructs, and forwards them to the subclass's constructor, accordingly.
Another way is to have a separate "parameters" class that would define, in some way, the parameters for the created object. It would allow those parameters to be specified. For this case, a std::vector would be appopriate. Then, your create() method would have to validate that the passed parameters are valid, and throw an exception otherwise, or something along the same lines.
I am not an expert on design patterns. So I am not sure if the following suggestions are still compatible with the factory pattern.
One way could be to create different methods like CreateObjectA(int a, int b, int c) and CreateObjectB(int a, int b). Another option could be to add a std::vector<int> to your method createObj. If all classes A, B, ... differ in the number of integers, the length of the vector could be used to decide which object to create. If this is not possible you could e.g. use some sort of ID to tell the factory which object to create.
Option 1
You could generalize your factory class using templates.
For instance, you could send the type you want to construct to the factory.
This is an example for what could be possible solution for your case:
struct Factory {
template<typename T, typename... Args>
T create(Args&&... args) {
return T{1, 2, std::forward<Args>(args)...};
}
};
It will be used like this:
Factory factory;
auto myA = factory.create<A>(1, 2, "an additional char* parameter");
// no additional parameter works too
auto myB = factory.create<B>();
Well, this class is pretty simple. It construct a type T with the arguments Args, plus two int parameter. But it will not allow making a different type depending on the value of a string though.
Btw you should replace every new in your code by std::make_unique, there where a lot of memory leaks in your code. Alternatively, you can create objects of the stack.
Option 2
If you know what type to construct depending on the parameters you send, you could just overload your function.
Here's what it would look like:
struct Factory {
A create(int a, int b, int c) {
return A{a, b, c};
}
B create(int a, int b) {
return B{a, b};
}
};
You could use it like this:
Factory factory;
auto myA = factory.create(1, 2, 3);
auto myB = factory.create(1, 2);
This might be easier to implement. But take note that you will not be able to have a class with two constructor neither you won't be able to have two class with the same parameters.

Pass lambda expression to lambda argument c++11

I would like to do something like this:
int main()
{
auto f = [/*some variables*/](/*take lambda function*/)
{/*something with lambda function*/};
f([/*other variables*/](/*variables to be decided by f()*/)
{/*something with variables*/});
}
I know that it is possible to pass a lambda to a function, as well as to a lambda.
The following works:
int main()
{
int x=0;
int y=0;
auto f = [x,y](double (func)(int)) -> double
{func(0); return 0.0;};
f([](int i) -> double
{return 0.0;});
}
But the following does not work (as soon as i change the scope variables to add [x])
int main()
{
int x=0;
int y=0;
auto f = [x,y](double (func)(int)) -> double
{func(0); return 0.0;}
f([x](int i) -> double //[x] does not work
{return 0.0;});
}
which gives the error:
error: function "lambda [](double (*)(int))->double::operator()" cannot be called with the given argument list
argument types are: (lambda [](int)->double)
object type is: lambda [](double (*)(int))->double
would anyone have an idea as to how to fix this, or a way around it?
I am using the intel compiler
icpc (ICC) 13.1.2 with std=c++11
Thanks
There are a couple of things to clarify regarding your question. The first of which is what is a lambda?
A lambda expression is a simple expression from which the compiler will generate a unique type that cannot be named, and at the same time it will generate an instance of the type. When you write: [](int i) { std::cout << i; } the compiler will generate a type for you that is roughly:
struct __lambda_unique_name {
void operator()(int i) const { std::cout << i; }
};
As you can see, it is not a function, but a type that implements operator() as a const member function. If the lambda did any capture, the compiler would generate code to capture the value/references.
As a corner case, for lambdas like the above, where there is no state being captured, the language allows for a conversion from the lambda type to a pointer to function with the signature of the operator() (minus the this part), so the lambda above can be implicitly converted to a pointer to function taking int and returning nothing:
void (*f)(int) = [](int i) { std::cout << i; }
Now that the basics have been stated, in your code you have this lambda:
auto f = [x,y](double (func)(int)) -> double {func(0); return 0.0;};
The rules for parameters to functions (that also apply to lambdas) determine that an argument cannot be of type function, so the argument to the lambda decays to a pointer to function (in the same way that an argument of type array decays to a pointer type):
auto f = [x,y](double (*func)(int)) -> double {func(0); return 0.0;};
At a later point you are trying to pass a lambda that has a capture as an argument. Because there is a capture, the special rule does not apply and the lambda is not convertible to a pointer to function yielding the compiler error that you see.
In the current standard you can go one of two ways. You can use type-erasure to remove the exact type of the callable entity from the signature:
auto f = [x,y](std::function<double(int)> func) -> double {func(0); return 0.0;};
Because a std::function<double(int)> can be initialized with any callable entity with the appropriate signature, this will accept the lambdas in the code below, at the cost of type-erasure that usually implies a dynamic allocation and dynamic dispatch.
Alternatively, you can drop the syntactic sugar and roll the first lambda equivalent manually, but make it generic. In this case, where the lambda is simple this could be a valid option:
struct mylambda {
template <typename F>
double operator()(F fn) const {
fn(0); return 0.0;
}
} f;
// then use the non-lambda as you tried:
f([x](int i) -> double {return 0.0;});
Finally, if you are patient enough, you can wait for C++14, where (most probably, it has not yet been ratified) there will be support for polymorphic lambdas which simplify the creation of the above class:
auto f = [](auto fn) { fn(0.0); return 0.0; } // unrolls to 'mylambda' above
Try using std::function:
#include <functional>
int main()
{
int x=0;
int y=0;
auto f = [x,y](std::function<double(int)> func) -> double
{func(0); return 0.0;};
f([x](int i) -> double {return 0.0;});
}
You may have to simply bite the bullet and implement your own functors like we did in the dark ages:
struct F {
int x;
int y;
F(int x_, int y_) : x(x_), y(y_) {}
template <typename G>
double operator() (G&& g) const {
g(0);
return 0.0;
}
};
#include <iostream>
int main()
{
int x = 0;
int y = 0;
auto f = F(x, y);
f([x](int i){return 0.0;});
f([](int i){std::cout << i << std::endl;});
}
That should keep you going until your compiler supports C++14 generic lambdas.
You could try something like the following if you know the type of the lambda beforehand, for instance:
int main()
{
int x = 0, y = 0;
auto f = [x]( int i )->double {
return (double)x;
};
auto f2 = [x,y]( decltype(f) func )->double {
return func( 0 );
};
f2( f );
return 0;
}
Or alternative you could use the <functional> library for a more generic solution, for instance:
auto f = [x,y]( std::function<double(int)> func ) { /* Do stuff */ };
You can cify a capturing lambda, but this solution has its limitations:
#include <new>
#include <utility>
namespace
{
template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...) noexcept(noexcept(
std::declval<F>()(std::declval<A>()...))))
{
static L l_(std::forward<L>(l));
static bool full;
if (full)
{
l_.~L();
new (static_cast<void*>(&l_)) L(std::forward<L>(l));
}
else
{
full = true;
}
return [](A... args) noexcept(noexcept(
std::declval<F>()(std::forward<A>(args)...))) -> R
{
return l_(std::forward<A>(args)...);
};
}
}
template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
return cify<F, I>(std::forward<L>(l), F());
}
int main()
{
int x=0;
int y=0;
auto f = [x,y](double (func)(int)) -> double
{func(0); return 0.0;};
f(cify<double(*)(int i)>([x](int i) -> double //works now
{return 0.0;}));
}
Click for a working example.