Discussion:
[std-proposals] why not formally support meta programming.
b***@gmail.com
2016-11-09 19:32:54 UTC
Permalink
I'm trying to design a library for different hardware (CPU and GPU)

For users, I want the interface looks like this:


Blah<GPU, float> b();

or

Blah<CPU, double> c();


ideally inside the class of Blah, I want to do this to avoid duplication
and reduce workload:



template<DeviceType deviceUsed, typename DataType>
class Blah
{
DataType shared_member;


#Meta_if(deviceUsed == GPU) //some kind of meta programming syntax
to enable code based on template
#{
DataType member_only_used_by_gpu;
void function_on_gpu();
#}


#Meta_if(deviceUsed == CPU)
#{
DataType member_only_used_by_cpu;
void function_on_cpu();
#}




void shared_function()
{
....
#Meta_if(deviceUsed = GPU) {
....
#}
}
};




This is the actual code I have right now.

as you can see, I have to use std::enable_if

I really don't like it, because it is a trick, a hacky solution, and only
works for functions, not for members or function internals.

and to make the following code to work, I had to try many options, some
don't compile, some don't do what I want. And It's really hard to
understand this syntax:

template<DeviceType T = DeviceUsed, typename Enabled = typename std::enable_if<(T & devices) != 0> >


template<DeviceType T = DeviceUsed, typename = std::enable_if<(T & devices) != 0>::type >


template<DeviceType T = DeviceUsed, typename std::enable_if<(T & devices) != 0>::type* = 0 >



And for class members, since std::enable_if can't be used, I have to put shared stuff into a base class. And this is only manageable to do when I have few template variables.






typedef enum


{


CPU_NAIVE = 0x1,


CPU = 0x2,


CPU_SIMD = 0x2,


GPU = 0x4,


GPU_CUDA = 0x4


} DeviceType;




#define DEVICE_SPECIFIC(devices) \


template<DeviceType T = DeviceUsed, typename Enabled = typename std::enable_if<(T & devices) != 0> >







template<typename DataType = float>


class Blob_base


{


protected:


const std::string m_name;


const unsigned int m_batchSize;


const unsigned int m_depth;


const unsigned int m_height;


const unsigned int m_width;


DataType *m_data;


};




template<DeviceType DeviceUsed = CPU, typename DataType = float>


class Blob : public Blob_base<DataType>


{




public:


Blob(const unsigned int batchSize,


const unsigned int depth,


const unsigned int height,


const unsigned int width,


const std::string &name = "no_name");




bool init();




DEVICE_SPECIFIC(CPU | GPU)


void test();


};




template<typename DataType>


class Blob<GPU, DataType> : public Blob_base<DataType>


{


public:


bool init();




Blob(const unsigned int batchSize,


const unsigned int depth,


const unsigned int height,


const unsigned int width,


const std::string &name = "no_name");


};




And because the limitation of partial specification of c++ (you have to
partially specify a class first before specifying its member functions), I
had to create many versions of the same class, with different template<>
variables.

I have to duplicate lots of code.

Also, I really want the flexibility to do this:

template<DeviceType device>
class
{
#meta_if(device == CPU || device == CPU_SIMD)
int a,b;
void function()
{... };
#meta_end
}


apparently using the base class still doesn't allow me to do this


I think many people share the same pain with me, if you google those
questions about std::enable_if and how to specify a template member
function.

So if meta programming is so useful, why don't you consider adding it
formally to C++ by introducing the above syntax, rather than standardizing
the partially working ugly hack std::enable_if?


PHP for example, can be mixed with html.

why can't c++ define something similar:

<?c++ echo 'While this is going to be parsed.'; ?>

such that what's inside <?c++ ... ?> will be executed by the preprocessor
and generate code?
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/668e0a04-c988-4354-ae32-30f626f75403%40isocpp.org.
Mikhail Maltsev
2016-11-09 19:46:40 UTC
Permalink
Post by b***@gmail.com
I'm trying to design a library for different hardware (CPU and GPU)
Blah<GPU, float> b();
or
Blah<CPU, double> c();
ideally inside the class of Blah, I want to do this to avoid duplication and
template<DeviceType deviceUsed, typename DataType>
class Blah
{
DataType shared_member;
#Meta_if(deviceUsed == GPU) //some kind of meta programming syntax
to enable code based on template
#{
DataType member_only_used_by_gpu;
void function_on_gpu();
#}
#Meta_if(deviceUsed == CPU)
#{
DataType member_only_used_by_cpu;
void function_on_cpu();
#}
void shared_function()
{
....
#Meta_if(deviceUsed = GPU) {
....
#}
}
};
C++17 will have constexpr if. It can be used in a function, but not in
a class definition. Actually the latter has been proposed earlier, but
rejected: https://isocpp.org/files/papers/n3613.pdf
--
Regads,
Mikhail Maltsev
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAOqAUTiRxwtmzM-_tSyTUKbyiJhivCbVmUgQ749ByD%3Dh-SAF4A%40mail.gmail.com.
Shi Yan
2016-11-09 20:11:55 UTC
Permalink
So what's the reason for rejection?
Post by b***@gmail.com
Post by b***@gmail.com
I'm trying to design a library for different hardware (CPU and GPU)
Blah<GPU, float> b();
or
Blah<CPU, double> c();
ideally inside the class of Blah, I want to do this to avoid duplication
and
Post by b***@gmail.com
template<DeviceType deviceUsed, typename DataType>
class Blah
{
DataType shared_member;
#Meta_if(deviceUsed == GPU) //some kind of meta programming
syntax
Post by b***@gmail.com
to enable code based on template
#{
DataType member_only_used_by_gpu;
void function_on_gpu();
#}
#Meta_if(deviceUsed == CPU)
#{
DataType member_only_used_by_cpu;
void function_on_cpu();
#}
void shared_function()
{
....
#Meta_if(deviceUsed = GPU) {
....
#}
}
};
C++17 will have constexpr if. It can be used in a function, but not in
a class definition. Actually the latter has been proposed earlier, but
rejected: https://isocpp.org/files/papers/n3613.pdf
--
Regads,
Mikhail Maltsev
--
You received this message because you are subscribed to a topic in the
Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/
isocpp.org/d/topic/std-proposals/dxjR3T_uGAk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
To view this discussion on the web visit https://groups.google.com/a/
isocpp.org/d/msgid/std-proposals/CAOqAUTiRxwtmzM-_
tSyTUKbyiJhivCbVmUgQ749ByD%3Dh-SAF4A%40mail.gmail.com.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAKO7S%3DJZi-v%3DEZiXFmUZnkMxARbVK5EJ6wmnC3NkqT_oSEQjOQ%40mail.gmail.com.
Nicol Bolas
2016-11-10 00:45:16 UTC
Permalink
A combination of `if constexpr` and template specialization can handle what
you're doing:

struct CPU_Device {};
struct GPU_Device {}

template<typename Device, typename DataType>
class BlahData;

template<typename DataType>
class BlahData<CPU_Device, DataType>
{
DataType member_only_used_by_cpu;
void function_on_cpu();
};

template<typename DataType>
class BlahData<GPU_Device, DataType>
{
DataType member_only_used_by_gpu;
void function_on_gpu();
};

template<typename Device, typename DataType>
class Blah : public BlahData<Device, DataType>
{
DataType shared_member;

void shared_function()
{
...
if constexpr(std::is_same<Device, GPU_Device>)
{
}
}
};

If you want to have `BlahData` functions be able to access the shared
members of `Blah`, then you'll need to have `BlahData` use the CRTP trick
to do so.
Post by Shi Yan
So what's the reason for rejection?
That it was really, really difficult to specify.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/f2877a3a-dd59-4a52-ab25-6458b9de3128%40isocpp.org.
b***@gmail.com
2016-11-10 01:11:00 UTC
Permalink
Thank you, this is indeed a cleaner solution.

but is if constexpr available with any compiler today? event prerelease
compiler, I'd like to try.
Post by Nicol Bolas
A combination of `if constexpr` and template specialization can handle
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/7d99e4bd-5ae1-4615-96dd-c8849487c007%40isocpp.org.
Shi Yan
2016-11-10 01:32:24 UTC
Permalink
I have tested on this page http://melpon.org/wandbox

that this feature is available with gcc 7 and clang 4.

I couldn't find how to obtain gcc 7 source code.

I will see if I could build clang 4
Post by b***@gmail.com
Thank you, this is indeed a cleaner solution.
but is if constexpr available with any compiler today? event prerelease
compiler, I'd like to try.
Post by Nicol Bolas
A combination of `if constexpr` and template specialization can handle
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAKO7S%3DKBacA_3p3z-payS4df2xe3HoYNekqg0wu0fXSjzwsTOw%40mail.gmail.com.
Thiago Macieira
2016-11-10 05:50:46 UTC
Permalink
Post by Shi Yan
I couldn't find how to obtain gcc 7 source code.
git://gcc.gnu.org/git/gcc.git

There's a faster clone in GitHub.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1990269.czQJ3d5rMr%40tjmaciei-mobl1.
'Michael Davies' via ISO C++ Standard - Future Proposals
2016-11-10 10:35:02 UTC
Permalink
I think that alternatively the other way to do this would be to use
ADL(Argument Dependent Lookup) based namespace composure.

You should look here:
https://svn.boost.org/trac/boost/wiki/BestPracticeHandbook

Essentially you would have something like this:
namespace CPU
{
struct Device {}; //tag

template<typename DataType, typename tag> void function_execution(DataType
data, tag) {...}
}

namespace GPU
{
struct Device {}; //tag

template<typename DataType, typename tag> void function_execution(DataType
data, tag) {...}
}

template<typename DeviceType, typename DataType>
class BlahData
{
void function(DataType data) { function_execution(data, DeviceType()); }
}

template<typename DeviceType, typename DataType>
class Blah : public BlahData<DeviceType, DataType>
{
DataType shared_member;

void shared_function()
{
function();
}
};

Obviously constexpr if is the way to go. But this, I think, is a possible
alternative if you aren't ready to move on to the next standard or you are
required to remain where you are.
Post by b***@gmail.com
I'm trying to design a library for different hardware (CPU and GPU)
Blah<GPU, float> b();
or
Blah<CPU, double> c();
ideally inside the class of Blah, I want to do this to avoid duplication
template<DeviceType deviceUsed, typename DataType>
class Blah
{
DataType shared_member;
#Meta_if(deviceUsed == GPU) //some kind of meta programming syntax
to enable code based on template
#{
DataType member_only_used_by_gpu;
void function_on_gpu();
#}
#Meta_if(deviceUsed == CPU)
#{
DataType member_only_used_by_cpu;
void function_on_cpu();
#}
void shared_function()
{
....
#Meta_if(deviceUsed = GPU) {
....
#}
}
};
This is the actual code I have right now.
as you can see, I have to use std::enable_if
I really don't like it, because it is a trick, a hacky solution, and only
works for functions, not for members or function internals.
and to make the following code to work, I had to try many options, some
don't compile, some don't do what I want. And It's really hard to
template<DeviceType T = DeviceUsed, typename Enabled = typename
std::enable_if<(T & devices) != 0> >
template<DeviceType T = DeviceUsed, typename = std::enable_if<(T & devices) != 0>::type >
template<DeviceType T = DeviceUsed, typename std::enable_if<(T & devices)
!= 0>::type* = 0 >
And for class members, since std::enable_if can't be used, I have to put
shared stuff into a base class. And this is only manageable to do when I
have few template variables.
typedef enum
{
CPU_NAIVE = 0x1,
CPU = 0x2,
CPU_SIMD = 0x2,
GPU = 0x4,
GPU_CUDA = 0x4
} DeviceType;
#define DEVICE_SPECIFIC(devices) \
template<DeviceType T = DeviceUsed, typename Enabled = typename
std::enable_if<(T & devices) != 0> >
template<typename DataType = float>
class Blob_base
{
const std::string m_name;
const unsigned int m_batchSize;
const unsigned int m_depth;
const unsigned int m_height;
const unsigned int m_width;
DataType *m_data;
};
template<DeviceType DeviceUsed = CPU, typename DataType = float>
class Blob : public Blob_base<DataType>
{
Blob(const unsigned int batchSize,
const unsigned int depth,
const unsigned int height,
const unsigned int width,
const std::string &name = "no_name");
bool init();
DEVICE_SPECIFIC(CPU | GPU)
void test();
};
template<typename DataType>
class Blob<GPU, DataType> : public Blob_base<DataType>
{
bool init();
Blob(const unsigned int batchSize,
const unsigned int depth,
const unsigned int height,
const unsigned int width,
const std::string &name = "no_name");
};
And because the limitation of partial specification of c++ (you have to
partially specify a class first before specifying its member functions), I
had to create many versions of the same class, with different template<>
variables.
I have to duplicate lots of code.
template<DeviceType device>
class
{
#meta_if(device == CPU || device == CPU_SIMD)
int a,b;
void function()
{... };
#meta_end
}
apparently using the base class still doesn't allow me to do this
I think many people share the same pain with me, if you google those
questions about std::enable_if and how to specify a template member
function.
So if meta programming is so useful, why don't you consider adding it
formally to C++ by introducing the above syntax, rather than standardizing
the partially working ugly hack std::enable_if?
PHP for example, can be mixed with html.
<?c++ echo 'While this is going to be parsed.'; ?>
such that what's inside <?c++ ... ?> will be executed by the preprocessor
and generate code?
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/215ef486-c593-4a7d-bb89-d134b18a9fab%40isocpp.org.
d***@gmail.com
2018-11-26 09:18:08 UTC
Permalink
20 years, no progress... Just replace C preprocessor with Lisp
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/03dc9a29-5756-42e4-8b94-2f69a9debb8f%40isocpp.org.
FrankHB1989
2018-11-29 04:25:52 UTC
Permalink
Post by d***@gmail.com
20 years, no progress... Just replace C preprocessor with Lisp
Lisp rocks here, but far from enough. Notably, traditional Lisp lacks
hygiene. Scheme may be better in this point, at the cost of specifying a
macro sublanguage as well.

But there is a problem come earlier: there are more than one way to do
metaprogramming
<https://en.wikipedia.org/wiki/Metaprogramming#Uses_in_programming_languages>.
And some
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0707r0.pdf>has
been proposed. However, I don't find an overall material to cover the whole
topic.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/b9197808-f239-4a39-80c2-974c88208051%40isocpp.org.
Loading...