220 29394 <215ef486-c593-4a7d-bb89-d134b18a9fab@isocpp.org> article
Path: news.gmane.org!.POSTED!not-for-mail
From: "'Michael Davies' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: why not formally support meta programming.
Date: Thu, 10 Nov 2016 02:35:02 -0800 (PST)
Lines: 558
Approved: news@gmane.org
Message-ID: <215ef486-c593-4a7d-bb89-d134b18a9fab@isocpp.org>
References: <668e0a04-c988-4354-ae32-30f626f75403@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_363_184363760.1478774102699"
X-Trace: blaine.gmane.org 1478774142 4527 195.159.176.226 (10 Nov 2016 10:35:42 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Thu, 10 Nov 2016 10:35:42 +0000 (UTC)
Cc: billconan@gmail.com
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBCS45AVH5YKBBV42SHAQKGQE32AQSOY@isocpp.org Thu Nov 10 11:35:38 2016
Return-path: <std-proposals+bncBCS45AVH5YKBBV42SHAQKGQE32AQSOY@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-yw0-f198.google.com ([209.85.161.198])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBCS45AVH5YKBBV42SHAQKGQE32AQSOY@isocpp.org>)
	id 1c4mhB-0004ao-F2
	for gclcip-std-proposals@m.gmane.org; Thu, 10 Nov 2016 11:35:01 +0100
Original-Received: by mail-yw0-f198.google.com with SMTP id t11sf269293139ywe.3
        for <gclcip-std-proposals@m.gmane.org>; Thu, 10 Nov 2016 02:35:04 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=date:from:to:cc:message-id:in-reply-to:references:subject
         :mime-version:x-original-sender:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=V2kBa8I6r8yMlME1mQAhWlqGy8PAVxnbPswjO0GYthA=;
        b=zPLg+t7mVvgAgYCwXD3j1CYWsn5s0FjFVKM/EYmLZKC8f1lobpyx6f6gnqMkouhXII
         bF9LlXlaMFjog34qjtDR8jyTQKmIan4pJdPPa9CiBV4tnzKSFQdNj7Bu4mCRpXDB2Ri0
         vniUaHHjEQCy8PyK3LYm2C9+lJep6n5Htm2jHKITQX+0uW7VpsSdPy9KLK0FoodUMYIw
         yPQpQ3AK5/YzeCHWPj9iHbx1FOSgeHPCET8T12cSPr79K/oo1AUPsqEthAHx7BXj98qL
         J9NZMeWvWggSAdKOBwsIYo51seqZdF7ssmmoQtcF6xh7UXpPm2DlcEb5wXMqvwjp5o5f
         Vu9g==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:date:from:to:cc:message-id:in-reply-to
         :references:subject:mime-version:x-original-sender:reply-to
         :precedence:mailing-list:list-id:x-spam-checked-in-group:list-post
         :list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=V2kBa8I6r8yMlME1mQAhWlqGy8PAVxnbPswjO0GYthA=;
        b=IbhSjluoOP1nfVIn6FhUBMl9O2tPcbj4TIrvhkm/2HSnKUcUCTq+uTveRxnvnQyh10
         5YPiBDzRjcGApL22xqxBgWSLcWWofEGFGtfEPeHlX7VCB2PTkgmmrWRbxMfMBRElv2E9
         8OfSgGr/taEp8DRSwSE4FTPQ9REyDodmwkKL6NMK5dyDVmV/MAkCQJ+glXrnJpxxMtiG
         SLppI9nu37dUu4kwCh6h7Y/zzTx2bZ5fb48wA2wXowIaaxiZINkqxjlh8qI9LqTwBr2C
         13FJqZLTXU4XSEN7EL85Wh7AkapT/s10T7EFbyqOwWaozktxc25kr4eTO3UxexMGFE4D
         7x6w==
X-Gm-Message-State: ABUngvepRcmFrYWzGA59lTRneH1qmA1eK1+gPVPuHf915v0GIVttB6Ui010fDPnyi1pSQA==
X-Received: by 10.13.227.67 with SMTP id m64mr908942ywe.36.1478774104442;
        Thu, 10 Nov 2016 02:35:04 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.157.43.24 with SMTP id o24ls6444145otb.41.gmail; Thu, 10 Nov
 2016 02:35:03 -0800 (PST)
X-Received: by 10.157.11.120 with SMTP id p53mr501826otd.19.1478774103541;
        Thu, 10 Nov 2016 02:35:03 -0800 (PST)
In-Reply-To: <668e0a04-c988-4354-ae32-30f626f75403@isocpp.org>
X-Original-Sender: MichaelDavies32@googlemail.com
X-Original-From: Michael Davies <michaeldavies32@googlemail.com>
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:29394
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/29394>

------=_Part_363_184363760.1478774102699
Content-Type: multipart/alternative; 
	boundary="----=_Part_364_2086495820.1478774102700"

------=_Part_364_2086495820.1478774102700
Content-Type: text/plain; charset=UTF-8

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.

On Wednesday, November 9, 2016 at 7:32:54 PM UTC, bill...@gmail.com wrote:
>
> 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+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@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.

------=_Part_364_2086495820.1478774102700
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I think that alternatively the other way to do this would =
be to use ADL(Argument Dependent Lookup) based namespace composure.<br><br>=
You should look here: <a href=3D"https://svn.boost.org/trac/boost/wiki/Best=
PracticeHandbook">https://svn.boost.org/trac/boost/wiki/BestPracticeHandboo=
k</a><br><br>Essentially you would have something like this:<br><div style=
=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-=
style:solid;border-width:1px"><code><div><span style=3D"color:#008">namespa=
ce CPU<br>{<br></span><div style=3D"margin-left: 40px;"><span style=3D"colo=
r:#008">struct</span><span style=3D"color:#000"> Device </span><span style=
=3D"color:#660">{};</span><span style=3D"color:#000"></span> <code><span st=
yle=3D"color:#000"></span><span style=3D"color:#660">//tag</span></code><br=
><br><code><code><span style=3D"color:#008"><code><code><span style=3D"colo=
r:#008">template&lt;typename </span></code><code><span style=3D"color:#008"=
><code><span style=3D"color:#000"></span><span style=3D"color:#606">DataTyp=
e</span><span style=3D"color:#660"></span></code>, typename </span></code><=
code><span style=3D"color:#000"></span><span style=3D"color:#606">tag</span=
><span style=3D"color:#660"></span></code><code><span style=3D"color:#008">=
<code><span style=3D"color:#660"></span></code>&gt;</span></code></code> vo=
id</span><span style=3D"color:#000"> function_execution</span><span style=
=3D"color:#660">(</span></code></code><code><code><span style=3D"color:#660=
"><code><code><code><span style=3D"color:#008"><code><code><span style=3D"c=
olor:#008"></span></code><code><span style=3D"color:#008"><code><span style=
=3D"color:#000"></span><span style=3D"color:#606">DataType</span><span styl=
e=3D"color:#660"> </span></code></span></code></code></span></code></code><=
/code></span></code></code><code><code><span style=3D"color:#660"><code><co=
de><code><span style=3D"color:#008"><code><code><span style=3D"color:#008">=
<code><span style=3D"color:#660"><code><code><span style=3D"color:#660"><co=
de><code><span style=3D"color:#000">data</span></code></code></span></code>=
</code></span></code></span></code></code></span></code></code></code>, </s=
pan></code></code><code><code><span style=3D"color:#660"></span></code><cod=
e><span style=3D"color:#660"><code><code><span style=3D"color:#008"></span>=
</code><code><span style=3D"color:#000"></span><span style=3D"color:#606">t=
ag</span><span style=3D"color:#660"></span></code><code><span style=3D"colo=
r:#008"><code><span style=3D"color:#660"></span></code></span></code></code=
></span></code></code><code><code><span style=3D"color:#660">) {...}</span>=
<span style=3D"color:#000"></span></code></code><br><span style=3D"color:#0=
00"></span></div><span style=3D"color:#008">}<br><br>namespace GPU<br>{<br>=
</span><div style=3D"margin-left: 40px;"><span style=3D"color:#008">struct<=
/span><span style=3D"color:#000"> Device </span><span style=3D"color:#660">=
{}</span><span style=3D"color:#000">; </span><code><code><span style=3D"col=
or:#000"></span><span style=3D"color:#660">//tag</span></code></code><br><b=
r><code><span style=3D"color:#000"></span><span style=3D"color:#008">templa=
te&lt;typename </span></code><code><span style=3D"color:#008"><code><span s=
tyle=3D"color:#000"></span><span style=3D"color:#606">DataType</span><span =
style=3D"color:#660"></span></code>, typename </span></code><code><span sty=
le=3D"color:#000"></span><span style=3D"color:#606">tag</span><span style=
=3D"color:#660"></span></code><code><span style=3D"color:#008"><code><span =
style=3D"color:#660"></span></code>&gt; void</span><span style=3D"color:#00=
0"> function_execution</span><span style=3D"color:#660">(</span></code><cod=
e><span style=3D"color:#660"><code><code><span style=3D"color:#008"></span>=
</code><code><span style=3D"color:#008"><code><span style=3D"color:#000"></=
span><span style=3D"color:#606">DataType </span></code></span></code></code=
></span></code><code><span style=3D"color:#660"><code><code><span style=3D"=
color:#000">data</span></code></code>, </span></code><code><span style=3D"c=
olor:#660"><code><code><span style=3D"color:#008"></span></code><code><span=
 style=3D"color:#000"></span><span style=3D"color:#606">tag</span><span sty=
le=3D"color:#660"></span></code><code><span style=3D"color:#008"><code><spa=
n style=3D"color:#660"></span></code></span></code></code>) {...}</span><sp=
an style=3D"color:#000"><br></span></code><span style=3D"color:#000"></span=
></div><span style=3D"color:#000">}<br><br></span><span style=3D"color:#008=
">template</span><span style=3D"color:#660">&lt;</span><span style=3D"color=
:#008">typename</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#606">DeviceType</span><span style=3D"color:#660">,</span><span style=3D=
"color:#000"> </span><span style=3D"color:#008">typename</span><span style=
=3D"color:#000"> </span><span style=3D"color:#606">DataType</span><span sty=
le=3D"color:#660">&gt;</span><span style=3D"color:#000"><br></span><span st=
yle=3D"color:#008">class</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#606">BlahData</span><span style=3D"color:#000"><br>{<br>=C2=A0=
 </span><span style=3D"color:#008">void</span><span style=3D"color:#000"> f=
unction</span><span style=3D"color:#660">(</span><span style=3D"color:#660"=
><code><span style=3D"color:#000"></span><span style=3D"color:#606">DataTyp=
e</span><span style=3D"color:#660"> </span></code></span><span style=3D"col=
or:#660"><code><span style=3D"color:#660"><code><code><span style=3D"color:=
#660"><code><code><span style=3D"color:#000">data</span></code></code></spa=
n></code></code></span></code>) { </span><span style=3D"color:#660"><code><=
code><span style=3D"color:#000">function_execution</span><span style=3D"col=
or:#660">(</span></code></code></span><span style=3D"color:#660"><code><cod=
e><span style=3D"color:#660"><code><code><span style=3D"color:#660"><code><=
code><span style=3D"color:#000">data</span></code></code></span></code></co=
de>, </span></code></code></span><span style=3D"color:#660"><code><code><sp=
an style=3D"color:#660"><code><span style=3D"color:#000"></span><span style=
=3D"color:#606">DeviceType</span><span style=3D"color:#660"></span></code>(=
));</span></code></code> }</span><span style=3D"color:#000"><br></span><spa=
n style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></span><s=
pan style=3D"color:#008">template</span><span style=3D"color:#660">&lt;</sp=
an><span style=3D"color:#008">typename</span><span style=3D"color:#000"> </=
span><span style=3D"color:#606">DeviceType</span><span style=3D"color:#660"=
>,</span><span style=3D"color:#000"> </span><span style=3D"color:#008">type=
name</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Da=
taType</span><span style=3D"color:#660">&gt;</span><span style=3D"color:#00=
0"><br></span><span style=3D"color:#008">class</span><span style=3D"color:#=
000"> </span><span style=3D"color:#606">Blah</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">:</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#008">public</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#606">BlahData</span><span style=3D"color:#660">=
&lt;</span><span style=3D"color:#606">DeviceType</span><span style=3D"color=
:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#606=
">DataType</span><span style=3D"color:#660">&gt;</span><span style=3D"color=
:#000"><br></span><span style=3D"color:#660">{</span><span style=3D"color:#=
000"><br>=C2=A0 </span><span style=3D"color:#606">DataType</span><span styl=
e=3D"color:#000"> shared_member</span><span style=3D"color:#660">;</span><s=
pan style=3D"color:#000"><br><br>=C2=A0 </span><span style=3D"color:#008">v=
oid</span><span style=3D"color:#000"> shared_function</span><span style=3D"=
color:#660">()</span><span style=3D"color:#000"><br>=C2=A0 </span><span sty=
le=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </sp=
an><code><span style=3D"color:#000">function();</span><span style=3D"color:=
#660"></span><span style=3D"color:#000"></span><span style=3D"color:#660"><=
/span></code><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"co=
lor:#660">}</span><span style=3D"color:#000"><br></span><span style=3D"colo=
r:#660">};</span></div></code></div><br>Obviously constexpr if is the way t=
o go. But this, I think, is a possible alternative if you aren&#39;t ready =
to move on to the next standard or you are required to remain where you are=
..<br><br>On Wednesday, November 9, 2016 at 7:32:54 PM UTC, bill...@gmail.co=
m wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;">I&#39;m trying to desi=
gn a library for different hardware (CPU and GPU)<p>For users, I want the i=
nterface looks like this:</p><p><br>Blah&lt;GPU, float&gt; b();</p><p>or </=
p><p>Blah&lt;CPU, double&gt; c();</p><p><br>ideally inside the class of Bla=
h, I want to do this to avoid duplication <br>and reduce workload:</p><p></=
p><p>template&lt;DeviceType deviceUsed, typename DataType&gt;<br>class Blah=
<br>{<br>=C2=A0 =C2=A0 =C2=A0 DataType shared_member;</p><p><br>=C2=A0 =C2=
=A0 =C2=A0 #Meta_if(deviceUsed =3D=3D GPU) =C2=A0 //some kind of meta progr=
amming syntax <br>to enable code based on template<br>=C2=A0 =C2=A0 =C2=A0 =
#{<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0DataType member_only_used_by=
_gpu;<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0void function_on_gpu();<b=
r>=C2=A0 =C2=A0 =C2=A0 #}</p><p><br>=C2=A0 =C2=A0 =C2=A0 #Meta_if(deviceUse=
d =3D=3D CPU)<br>=C2=A0 =C2=A0 =C2=A0 #{<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 DataType member_only_used_by_cpu;<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 void function_on_cpu();<br>=C2=A0 =C2=A0 =C2=A0 #}</p><p></p><p><br>=C2=A0=
 =C2=A0 =C2=A0 void shared_function()<br>=C2=A0 =C2=A0 =C2=A0 { <br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ....<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 #Meta_if(deviceUsed =3D GPU) {<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0....<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 #}<br>=C2=A0=
 =C2=A0 =C2=A0 }<br>};</p><p></p><p><br>This is the actual code I have righ=
t now.</p><p>as you can see, I have to use std::enable_if</p><p>I really do=
n&#39;t like it, because it is a trick, a hacky solution, and only <br>work=
s for functions, not for members or function internals.</p><p>and to make t=
he following code to work, I had to try many options, some <br>don&#39;t co=
mpile, some don&#39;t do what I want. And It&#39;s really hard to <br>under=
stand this syntax:</p><p>template&lt;DeviceType T =3D DeviceUsed, typename =
Enabled =3D typename std::enable_if&lt;(T &amp; devices) !=3D 0&gt; &gt;</p=
><p><br>template&lt;DeviceType T =3D DeviceUsed, typename =3D std::enable_i=
f&lt;(T &amp; devices) !=3D 0&gt;::type &gt;</p><p><br>template&lt;DeviceTy=
pe T =3D DeviceUsed, typename std::enable_if&lt;(T &amp; devices) !=3D 0&gt=
;::type* =3D 0 &gt;</p><p></p><p>And for class members, since std::enable_i=
f can&#39;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. </p><p></p><p=
></p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 typedef enum </p><p><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 {</p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 CPU_NAIVE =C2=A0 =C2=A0 =C2=A0=3D 0x1,</p><p><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CPU =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0=3D 0x2,</p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 CPU_SIMD =C2=A0 =C2=A0 =C2=A0 =3D 0x2,</p><p><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 GPU =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0=3D 0x4,</p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 GPU_CUDA =C2=A0 =C2=A0 =C2=A0 =3D 0x4</p><p><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 } DeviceType;</p><p></p><p><br>#define DEVICE_SPECIFIC=
(devices) \</p><p><br>=C2=A0 =C2=A0 template&lt;DeviceType T =3D DeviceUsed=
, typename Enabled =3D typename std::enable_if&lt;(T &amp; devices) !=3D 0&=
gt; &gt;</p><p></p><p></p><p><br>=C2=A0<br>=C2=A0 =C2=A0template&lt;typenam=
e DataType =3D float&gt;</p><p><br>=C2=A0 =C2=A0 class Blob_base</p><p><br>=
=C2=A0 =C2=A0 {</p><p><br>=C2=A0 =C2=A0 protected:</p><p><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 const std::string m_name;</p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 const unsigned int m_batchSize;</p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 c=
onst unsigned int m_depth;</p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 const unsi=
gned int m_height;</p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 const unsigned int=
 m_width;</p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 DataType *m_data;</p><p><br=
>=C2=A0 =C2=A0 };</p><p></p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 template&lt;=
DeviceType DeviceUsed =3D CPU, typename DataType =3D float&gt;</p><p><br>=
=C2=A0 =C2=A0 class Blob : public Blob_base&lt;DataType&gt;</p><p><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 {</p><p></p><p><br>=C2=A0 =C2=A0 public:</p><p><br=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Blob(const unsigne=
d int batchSize, </p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0const unsigned int depth,</p><=
p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0const unsigned int height,</p><p><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0co=
nst unsigned int width,</p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0const std::string &amp;nam=
e =3D &quot;no_name&quot;);</p><p></p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 bo=
ol init();</p><p></p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 DEVICE_SPECIFIC(CPU | GPU)</p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 void test();</p><p><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 };</p><p></p><p><br>=C2=A0 =C2=A0 template&lt;typename DataType&gt;<=
/p><p><br>=C2=A0 =C2=A0 class Blob&lt;GPU, DataType&gt; : public Blob_base&=
lt;DataType&gt;</p><p><br>=C2=A0 =C2=A0 {</p><p><br>=C2=A0 =C2=A0 public:</=
p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 bool init();</p><p></p><p><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 Blob(const unsigned int batchSize,</p><p><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0const unsigned int depth,</p><p><b=
r>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0const unsigned int height=
,</p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0const unsigned =
int width,</p><p><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0const =
std::string &amp;name =3D &quot;no_name&quot;);</p><p><br>=C2=A0 =C2=A0 };<=
/p><p></p><p><br>And because the limitation of partial specification of c++=
 (you have to <br>partially specify a class first before specifying its mem=
ber functions), I <br>had to create many versions of the same class, with d=
ifferent template&lt;&gt; <br>variables.</p><p>I have to duplicate lots of =
code.</p><p>Also, I really want the flexibility to do this:</p><p>template&=
lt;DeviceType device&gt;<br>class<br>{<br>=C2=A0 =C2=A0 =C2=A0 #meta_if(dev=
ice =3D=3D CPU || device =3D=3D CPU_SIMD)<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0int=
 a,b;<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0void function()<br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0{... };<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0#meta_end<br>}</p><p><br>appar=
ently using the base class still doesn&#39;t allow me to do this </p><p><br=
>I think many people share the same pain with me, if you google those <br>q=
uestions about std::enable_if and how to specify a template member <br>func=
tion.</p><p>So if meta programming is so useful, why don&#39;t you consider=
 adding it <br>formally to C++ by introducing the above syntax, rather than=
 standardizing <br>the partially working ugly hack std::enable_if?</p><p><b=
r>PHP for example, can be mixed with html.</p><p>why can&#39;t c++ define s=
omething similar:</p><p>&lt;?c++ echo &#39;While this is going to be parsed=
..&#39;; ?&gt;</p><p>such that what&#39;s inside &lt;?c++ ... ?&gt; will be =
executed by the preprocessor <br>and generate code?</p><p></p><p></p><p></p=
><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p><=
/p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p=
></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p>=
<p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></=
p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p>=
</p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><=
p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p=
><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p><=
/p><p></p><p></p><p></p></blockquote></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/215ef486-c593-4a7d-bb89-d134b18a9fab%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/215ef486-c593-4a7d-bb89-d134b18a9fab=
%40isocpp.org</a>.<br />

------=_Part_364_2086495820.1478774102700--

------=_Part_363_184363760.1478774102699--

.
