使用 std::enable_if 与复杂谓词。

huangapple go评论66阅读模式
英文:

Using std::enable_if with complex predicates

问题

使用 typename std::enable_if<IsVector<T>::value || IsList<T>::value, void>::type 作为约束条件时,它可以正常工作。如果使用 typename std::enable_if<IsVectorOrList<T>::value>::type,编译器会报错。

如何让它正常工作呢?

英文:

Having to use C++14 I'd like to use std::enable_if to make a function only being available given certain constraints. I do so using or_&lt;&gt; taken from the libc header type_traits instead of std::disjunction (no C++17 available in my environment) in order to move the constraint logic into a separate construct.

However, I seem to be missing something, because I can't manage to get it to compile.

My code:

#include &lt;type_traits&gt;
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;list&gt;

template &lt;typename T&gt;
struct IsVector : public std::false_type {};

template &lt;typename T&gt;
struct IsVector&lt;std::vector&lt;T&gt;&gt; : public std::true_type {};

template &lt;typename T&gt;
struct IsList : public std::false_type {};

template &lt;typename T&gt;
struct IsList&lt;std::list&lt;T&gt;&gt; : public std::true_type {};

// taken from libc type_traits
template &lt;bool, typename, typename&gt;
struct conditional;

template &lt;typename...&gt;
struct or_;

template &lt;&gt;
struct or_&lt;&gt; : public std::false_type {};

template &lt;typename _B1&gt;
struct or_&lt;_B1&gt; : public _B1 {};

template &lt;typename _B1, typename _B2&gt;
struct or_&lt;_B1, _B2&gt; : public conditional&lt;_B1::value, _B1, _B2&gt;::type {};

template &lt;typename _B1, typename _B2, typename _B3, typename... _Bn&gt;
struct or_&lt;_B1, _B2, _B3, _Bn...&gt; : public conditional&lt;_B1::value, _B1, or_&lt;_B2, _B3, _Bn...&gt;&gt;::type {};
// ---

template &lt;typename T&gt;
struct IsVectorOrList : public or_&lt;IsVector&lt;T&gt;, IsList&lt;T&gt;&gt;::type {};

template &lt;typename T&gt;
typename std::enable_if&lt;IsVector&lt;T&gt;::value || IsList&lt;T&gt;::value, void&gt;::type
// replacing with this line does not work
//typename std::enable_if&lt;IsVectorOrList&lt;T&gt;::value, void&gt;::type
foo(const T&amp; list)
{
    for (const auto&amp; item : list)
    {
        std::cout &lt;&lt; item &lt;&lt; std::endl;
    }
}


int main()
{
    foo(std::vector&lt;int&gt;{17, 42});
    foo(std::list&lt;float&gt;{1.0, 2.71, 3.14});
}

When using typename std::enable_if&lt;IsVector&lt;T&gt;::value || IsList&lt;T&gt;::value, void&gt;::type as constraint it works fine. If I use typename std::enable_if&lt;IsVectorOrList&lt;T&gt;::value&gt;::type the compiler complains:

traits.cpp:32:8: error: invalid use of incomplete type ‘struct conditional&lt;true, IsVector&lt;std::vector&lt;int&gt; &gt;, IsList&lt;std::vector&lt;int&gt; &gt; &gt;’
32 | struct or_&lt;_B1, _B2&gt; : public conditional&lt;_B1::value, _B1, _B2&gt;::type {};
|        ^~~~~~~~~~~~~
traits.cpp:20:8: note: declaration of ‘struct conditional&lt;true, IsVector&lt;std::vector&lt;int&gt; &gt;, IsList&lt;std::vector&lt;int&gt; &gt; &gt;’
20 | struct conditional;
|        ^~~~~~~~~~~

How do I make it work?

答案1

得分: 2

以下是翻译好的部分:

"// taken from libc type_traits" -> "// 从 libc type_traits 中获取"

"The code declares conditional, but that class isn't defined anywhere in the posted snippet." -> "这段代码声明conditional,但该类在发布的片段中没有定义。"

"Removing those lines and using std::conditional the code works." -> "删除这些行并使用 std::conditional 代码可以正常工作。"

英文:

Here:

// taken from libc type_traits
template &lt;bool, typename, typename&gt;
struct conditional;

The code declares conditional, but that class isn't defined anywhere in the posted snippet.

Removing those lines and using std::conditional the code works.

huangapple
  • 本文由 发表于 2023年7月6日 21:01:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76629125.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定