b***@gmail.com
2016-11-09 19:32:54 UTC
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?
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.
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.