<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[c++ boost enable_if]]></title><description><![CDATA[<p>Hi,<br />
Ich raff diese enable_if Geschichte nicht so richtig.</p>
<p>Ich habe eine Templateklasse mit einem Dimensionsparameter.</p>
<pre><code class="language-cpp">template&lt; typename TYPE, int DIM &gt;
class TPoint{
  public: 
   // operator []
  private:
   std::array&lt;TYPE, DIM&gt; m_data;
}
</code></pre>
<p>Als Komfortfeature würde ich gern für Dimensionen 2 und 3 entsprechende Memberfunktionen zum lesen und schreiben von x,y,z einfügen, die aber nur bei DIM 2 oder 3 aktiv sein sollen.</p>
<pre><code class="language-cpp">TYPE getX() const;
//und 
void setX( TYPE newx );
</code></pre>
<p>Anstelle von Spezialisierung und der damit verbundenen Codeduplizierung wollte ich gerne das enable_if benutzen.</p>
<p>Aber ich weiß nicht, wie ich es aufschreiben soll.</p>
<p>Ich hab folgende Traits definiert:</p>
<pre><code class="language-cpp">template &lt;int DIM&gt;  struct is_dimGte2   { static const bool value = false; };
  template &lt;       &gt;  struct is_dimGte2&lt;2&gt;{ static const bool value = true;  };
  template &lt;       &gt;  struct is_dimGte2&lt;3&gt;{ static const bool value = true;  };
  template &lt;int DIM&gt;  struct is_dimGte3   { static const bool value = false; };
  template &lt;       &gt;  struct is_dimGte3&lt;3&gt;{ static const bool value = true;  };
</code></pre>
<p>und so die funktion deklariert</p>
<pre><code class="language-cpp">typename boost::enable_if_c&lt;is_dimGte2&lt;DIM&gt;::value, TYPE&gt;::type 
    getY() { return data[2]; }
</code></pre>
<p>jetzt kann ich aber nur noch TPoint&lt;2&gt; und TPoint&lt;3&gt; erzeugen<br />
kann mir vielleicht jemand einen Tip geben?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/307940/c-boost-enable_if</link><generator>RSS for Node</generator><lastBuildDate>Thu, 06 Aug 2026 08:08:32 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/307940.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 10 Sep 2012 08:00:08 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to c++ boost enable_if on Mon, 10 Sep 2012 08:47:30 GMT]]></title><description><![CDATA[<p>Hi,<br />
Ich raff diese enable_if Geschichte nicht so richtig.</p>
<p>Ich habe eine Templateklasse mit einem Dimensionsparameter.</p>
<pre><code class="language-cpp">template&lt; typename TYPE, int DIM &gt;
class TPoint{
  public: 
   // operator []
  private:
   std::array&lt;TYPE, DIM&gt; m_data;
}
</code></pre>
<p>Als Komfortfeature würde ich gern für Dimensionen 2 und 3 entsprechende Memberfunktionen zum lesen und schreiben von x,y,z einfügen, die aber nur bei DIM 2 oder 3 aktiv sein sollen.</p>
<pre><code class="language-cpp">TYPE getX() const;
//und 
void setX( TYPE newx );
</code></pre>
<p>Anstelle von Spezialisierung und der damit verbundenen Codeduplizierung wollte ich gerne das enable_if benutzen.</p>
<p>Aber ich weiß nicht, wie ich es aufschreiben soll.</p>
<p>Ich hab folgende Traits definiert:</p>
<pre><code class="language-cpp">template &lt;int DIM&gt;  struct is_dimGte2   { static const bool value = false; };
  template &lt;       &gt;  struct is_dimGte2&lt;2&gt;{ static const bool value = true;  };
  template &lt;       &gt;  struct is_dimGte2&lt;3&gt;{ static const bool value = true;  };
  template &lt;int DIM&gt;  struct is_dimGte3   { static const bool value = false; };
  template &lt;       &gt;  struct is_dimGte3&lt;3&gt;{ static const bool value = true;  };
</code></pre>
<p>und so die funktion deklariert</p>
<pre><code class="language-cpp">typename boost::enable_if_c&lt;is_dimGte2&lt;DIM&gt;::value, TYPE&gt;::type 
    getY() { return data[2]; }
</code></pre>
<p>jetzt kann ich aber nur noch TPoint&lt;2&gt; und TPoint&lt;3&gt; erzeugen<br />
kann mir vielleicht jemand einen Tip geben?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2249838</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2249838</guid><dc:creator><![CDATA[vlad_tepesch]]></dc:creator><pubDate>Mon, 10 Sep 2012 08:47:30 GMT</pubDate></item><item><title><![CDATA[Reply to c++ boost enable_if on Mon, 10 Sep 2012 08:59:44 GMT]]></title><description><![CDATA[<p>vlad_tepesch schrieb:</p>
<blockquote>
<p>und so die funktion deklariert</p>
<pre><code class="language-cpp">typename boost::enable_if_c&lt;is_dimGte2&lt;DIM&gt;::value, TYPE&gt;::type 
    getY() { return data[2]; }
</code></pre>
</blockquote>
<p>SFINAE bezieht sich auf Funktions<em>templates</em>, nicht auf normale Funktionen. Auch dann nicht, wenn diese Funktionen zufällig Member einer Templateklasse sind.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2249856</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2249856</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Mon, 10 Sep 2012 08:59:44 GMT</pubDate></item><item><title><![CDATA[Reply to c++ boost enable_if on Mon, 10 Sep 2012 09:37:54 GMT]]></title><description><![CDATA[<p>*Klassentemplate :p</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2249879</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2249879</guid><dc:creator><![CDATA[Kellerautomat]]></dc:creator><pubDate>Mon, 10 Sep 2012 09:37:54 GMT</pubDate></item><item><title><![CDATA[Reply to c++ boost enable_if on Mon, 10 Sep 2012 09:42:50 GMT]]></title><description><![CDATA[<p>Ich würde das per CRTP lösen, etwa so:</p>
<pre><code class="language-cpp">template&lt;typename Type, typename ValueType, unsigned DIM&gt;
class TPointImpl {
};

template&lt;typename Type, typename ValueType&gt;
class TPointImpl&lt;Type, ValueType, 2&gt; {
public:
        void setX(ValueType val) {
                static_cast&lt;Type*&gt;(this)-&gt;set(0, val);
        }

        void setY(ValueType val) {
                static_cast&lt;Type*&gt;(this)-&gt;set(1, val);
        }
};

template&lt;typename T, unsigned DIM&gt;
class TPoint : public TPointImpl&lt;TPoint&lt;T,DIM&gt;, T, DIM&gt; {
public:
        typedef T value_type;
private:
        T data[DIM];
public:
        void set(unsigned dim, value_type val) {
                data[dim]=val;
        }

};

int main() {
        TPoint&lt;int, 2&gt; p;

        p.setX(7);

}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2249885</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2249885</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Mon, 10 Sep 2012 09:42:50 GMT</pubDate></item><item><title><![CDATA[Reply to c++ boost enable_if on Mon, 10 Sep 2012 13:04:01 GMT]]></title><description><![CDATA[<p>Ich stand neulich vor genau demselben Problem, auch für eine point-Klasse <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /> Ich hab's dann in etwa so gelöst, wobei mich aber auch alternative Vorschläge interessieren würden.</p>
<pre><code class="language-cpp">enum no_init_tag {no_init};

template&lt;class T, int Dim, class Derived&gt;
struct point_base : std::array&lt;T,Dim&gt;
{
  .....
  point_base()
  { std::fill(this-&gt;begin(),this-&gt;end(),T(0)); }

  explicit point_base(no_init_tag)
  {}

  Derived&amp; operator+=(Derived const&amp; x)
  {
    blas::axpy(Dim,1,x.begin(),this-&gt;begin());
    return self();
  }
  .....
  Alles möglich andere noch
  .....
protected:
  Derived      &amp; self()       {return static_cast&lt;Derived      &amp;&gt;(*this);}
  Derived const&amp; self() const {return static_cast&lt;Derived const&amp;&gt;(*this);}
};

template&lt;class T, int Dim&gt;
struct point : point_base&lt;T,Dim,point&lt;T,Dim&gt; &gt;
{};

template&lt;class T&gt;
struct point&lt;T,2&gt; : point_base&lt;T,2,point&lt;T,2&gt; &gt;
{
  typedef point_base&lt;T,2,point&lt;T,2&gt; &gt; base_type;
  point()
  {}
  point(T x, T y)
  : base_type(no_init)
  { (*this)[0] = x; (*this)[1] = y; }

  void setX(T x){(*this)[0]=x;}
  void setY(T y){(*this)[1]=y;}
};
</code></pre>
<p>Also: Der gemeinsame Kram ist in point_base drin und die speziellen Konstruktoren gibt's dann in der Spezialisierung einer abgeleiteten Klasse.</p>
<p>So richtig dolle gefällt mir dieser Workaround nicht. Aber was viel besseres fällt mir auch nicht ein. Mit 'nem variadischen Konstruktortemplate könnte man es ja auch regeln, allerdings unterstützt das der Compiler von Microsoft noch nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2249887</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2249887</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Mon, 10 Sep 2012 13:04:01 GMT</pubDate></item><item><title><![CDATA[Reply to c++ boost enable_if on Mon, 10 Sep 2012 10:18:15 GMT]]></title><description><![CDATA[<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>Ich würde das per CRTP lösen, etwa so:</p>
</blockquote>
<p>Danke, das sieht super aus.<br />
Das einzige was mich daran stört, ist, dass man den namespace mit internen Typen vollmüllt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2249892</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2249892</guid><dc:creator><![CDATA[vlad_tepesch]]></dc:creator><pubDate>Mon, 10 Sep 2012 10:18:15 GMT</pubDate></item><item><title><![CDATA[Reply to c++ boost enable_if on Mon, 10 Sep 2012 10:29:46 GMT]]></title><description><![CDATA[<p>vlad_tepesch schrieb:</p>
<blockquote>
<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>Ich würde das per CRTP lösen, etwa so:</p>
</blockquote>
<p>Danke, das sieht super aus.<br />
Das einzige was mich daran stört, ist, dass man den namespace mit internen Typen vollmüllt.</p>
</blockquote>
<p>Du kannst *Impl ja auch in einen anderen Namespace stecken.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2249896</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2249896</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Mon, 10 Sep 2012 10:29:46 GMT</pubDate></item><item><title><![CDATA[Reply to c++ boost enable_if on Mon, 10 Sep 2012 17:32:58 GMT]]></title><description><![CDATA[<p>Da in C++11 auch die Templateparameter von Funktionstemplates Defaultargumente haben dürfen, kann im Prinzip jede Funktion in ein Template umgewandelt werden</p>
<pre><code class="language-cpp">template &lt;bool a, bool b&gt; struct and_ : std::integral_constant&lt;bool, a &amp;&amp; b&gt; {};

template &lt;typename T, size_t N&gt;
class point
{
public:
    template &lt;typename U = void, typename std::enable_if&lt;and_&lt;N==2||N==3, std::is_same&lt;U,void&gt;::value&gt;::value, int&gt;::type = 0&gt;
    const T&amp; get_x() const { return (*this)[0]; }
    template &lt;typename U = void, typename std::enable_if&lt;and_&lt;N==2||N==3, std::is_same&lt;U,void&gt;::value&gt;::value, int&gt;::type = 0&gt;
    const T&amp; get_y() const { return (*this)[1]; }
    template &lt;typename U = void, typename std::enable_if&lt;and_&lt;N==3,       std::is_same&lt;U,void&gt;::value&gt;::value, int&gt;::type = 0&gt;
    const T&amp; get_z() const { return (*this)[2]; }
    const T&amp; operator[](size_t i) const { return m_data[i]; }
// ...
private:
   std::array&lt;T, N&gt; m_data;
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2250041</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2250041</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Mon, 10 Sep 2012 17:32:58 GMT</pubDate></item><item><title><![CDATA[Reply to c++ boost enable_if on Mon, 10 Sep 2012 18:11:45 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<pre><code class="language-cpp">template &lt;bool a, bool b&gt; struct and_ : std::integral_constant&lt;bool, a &amp;&amp; b&gt; {};

template &lt;typename T, size_t N&gt;
class point
{
public:
    template &lt;typename U = void, typename std::enable_if&lt;and_&lt;N==2||N==3, std::is_same&lt;U,void&gt;::value&gt;::value, int&gt;::type = 0&gt;
    const T&amp; get_x() const { return (*this)[0]; }
    template &lt;typename U = void, typename std::enable_if&lt;and_&lt;N==2||N==3, std::is_same&lt;U,void&gt;::value&gt;::value, int&gt;::type = 0&gt;
    const T&amp; get_y() const { return (*this)[1]; }
    template &lt;typename U = void, typename std::enable_if&lt;and_&lt;N==3,       std::is_same&lt;U,void&gt;::value&gt;::value, int&gt;::type = 0&gt;
    const T&amp; get_z() const { return (*this)[2]; }
    const T&amp; operator[](size_t i) const { return m_data[i]; }
// ...
private:
   std::array&lt;T, N&gt; m_data;
};
</code></pre>
</blockquote>
<p>Muss das so kompliziert? Was spricht denn gegen</p>
<pre><code class="language-cpp">template &lt;typename T, size_t N&gt;
class point
{
public:
    template &lt;class = typename std::enable_if&lt;(N==2||N==3)&gt;::type&gt;
    const T&amp; get_x() const { return (*this)[0]; }
    template &lt;class = typename std::enable_if&lt;(N==2||N==3)&gt;::type&gt;
    const T&amp; get_y() const { return (*this)[1]; }
    template &lt;class = typename std::enable_if&lt;(      N==3)&gt;::type&gt;
    const T&amp; get_z() const { return (*this)[2]; }
    const T&amp; operator[](size_t i) const { return m_data[i]; }
// ...
private:
   std::array&lt;T, N&gt; m_data;
};
</code></pre>
<p>?</p>
<p>Edit: Gut, das schützt nicht wirklich davor, dass jemand get_x&lt;void&gt;() schreibt. Insofern ist das, was du gezeigt hast, &quot;idiotensicher&quot; -- wobei das and_ aber trotzdem überflüssug aussieht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2250051</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2250051</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Mon, 10 Sep 2012 18:11:45 GMT</pubDate></item><item><title><![CDATA[Reply to c++ boost enable_if on Mon, 10 Sep 2012 18:31:35 GMT]]></title><link>https://www.c-plusplus.net/forum/post/2250059</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2250059</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Mon, 10 Sep 2012 18:31:35 GMT</pubDate></item><item><title><![CDATA[Reply to c++ boost enable_if on Mon, 10 Sep 2012 20:36:59 GMT]]></title><description><![CDATA[<p>krümelkacker schrieb:</p>
<blockquote>
<p>Muss das so kompliziert? Was spricht denn gegen</p>
<pre><code class="language-cpp">template &lt;typename T, size_t N&gt;
class point
{
public:
    template &lt;class = typename std::enable_if&lt;(N==2||N==3)&gt;::type&gt;
    const T&amp; get_x() const { return (*this)[0]; }
    template &lt;class = typename std::enable_if&lt;(N==2||N==3)&gt;::type&gt;
    const T&amp; get_y() const { return (*this)[1]; }
    template &lt;class = typename std::enable_if&lt;(      N==3)&gt;::type&gt;
    const T&amp; get_z() const { return (*this)[2]; }
    const T&amp; operator[](size_t i) const { return m_data[i]; }
// ...
private:
   std::array&lt;T, N&gt; m_data;
};
</code></pre>
</blockquote>
<p>Das ist ill-formed für alle N!=3. Bei der Instantiierung von point&lt;T,N&gt; werden auch alle Memberdeklarationen instantiiert. Da</p>
<pre><code class="language-cpp">typename std::enable_if&lt;(N==2||N==3)&gt;::type
</code></pre>
<p>nicht von einem Templateparamter des Funktionstemplates selbst abhängt, wird der Bezeichner an dieser Stelle gebunden. Und weil es sich dabei nicht um einen Typ handelt (enable_if&lt;false&gt;::type existiert ja nicht), ist die Deklaration ill-formed. Und weil es hier nicht um die Zusammenstellung eines Überladungssets geht, greift SFINAE nicht.</p>
<p>and_ mag in diesem Zusammenhang übertrieben sein</p>
<pre><code class="language-cpp">template &lt;bool b = true, typename std::enable_if&lt;(N==2||N==3)&amp;&amp;b, int&gt;::type = 0&gt;
    const T&amp; get_x() const { return (*this)[0]; }
</code></pre>
<p>funktioniert wahrscheinlich auch. Ganz sicher bin ich mir aber nicht (14.6/8).</p>
<p>Edit:</p>
<pre><code class="language-cpp">template &lt;bool enable = N==2||N==3, typename std::enable_if&lt;enable, int&gt;::type = 0&gt;
    const T&amp; get_x() const { return (*this)[0]; }
</code></pre>
<p>ist simpel und problemlos. Ganz nebenbei kann man die Funktion auch für andere N explizit benutzen, was zumindest in diesem Fall nicht unbedingt sinnlos ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2250100</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2250100</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Mon, 10 Sep 2012 20:36:59 GMT</pubDate></item><item><title><![CDATA[Reply to c++ boost enable_if on Mon, 10 Sep 2012 21:22:11 GMT]]></title><description><![CDATA[<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /><br />
danke für den beitrag!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2250113</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2250113</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Mon, 10 Sep 2012 21:22:11 GMT</pubDate></item></channel></rss>