如何根据条件限制用户定义的模板类型。

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

How to restrict userdefined template types based on a condition

问题

class CMyClass<typename VarTypes>
{
// do something
};

当前代码接受多个VarTypes,例如Type1、Type2,而不受任何条件限制(例如编译器选项)。

我想要根据条件限制VarTypes。有经验吗?

英文:
template&lt;typename VarTypes&gt;
class CMyClass
{
   // do something
};

currently the code accepts multiple VarTypes Type1, Type2 irrespective of any condition (example compiler option).

I have to like to restrict VarTypes based on the conditions. any experience?

答案1

得分: 3

I would keep it simple and just use static_assert, e.g.:

template&lt;typename T&gt;
class CMyClass
{
#if defined(VARIANT1)
    static_assert (std::is_same &lt;T, std::string&gt;::value ||
                   std::is_same &lt;T, std::vector &lt;int&gt;&gt;::value, &quot;Type not allowed&quot;);
#elif defined(VARIANT2)
    ...
#endif

    // do something
};

Live demo

英文:

I would keep it simple and just use static_assert, e.g.:

template&lt;typename T&gt;
class CMyClass
{
#if defined(VARIANT1)
    static_assert (std::is_same &lt;T, std::string&gt;::value ||
                   std::is_same &lt;T, std::vector &lt;int&gt;&gt;::value, &quot;Type not allowed&quot;);
#elif defined(VARIANT2)
    ...
#endif

    // do something
};

Live demo

答案2

得分: 2

You could define a std::tuple based type to describe the accepted types and then use SFINAE to enable instantiating a class from the template based on that.

Example (replace with your own types as needed):

#include <tuple>

#if defined(VARIANT1)
using accepted_types = std::tuple <std::string, std::set<int>>;
#elif defined(VARIANT2)
using accepted_types = std::tuple <std::map<int,int>, std::vector<int>>;
#endif

Then we need a has_type type trait to check if one type is included in a std::tuple based type (see link to that answer for the full description):

#include <type_traits>

template <typename T, typename Tuple>
struct has_type;

template <typename T>
struct has_type<T, std::tuple<>> : std::false_type {};

template <typename T, typename U, typename... Ts>
struct has_type<T, std::tuple<U, Ts...>> : has_type<T, std::tuple<Ts...>> {};

template <typename T, typename... Ts>
struct has_type<T, std::tuple<T, Ts...>> : std::true_type {};

template<class T, class V>
static constexpr bool has_type_v = has_type<T, V>::value;

Then enable the template only for those types included in accepted_types:

template <typename VarType,
          typename = std::enable_if_t<has_type_v<VarType, accepted_types>>>
class CMyClass {

};

Demo

英文:

You could define a std::tuple based type to describe the accepted types and then use SFINAE to enable instantiating a class from the template based on that.

Example (replace with your own types as needed):

#include &lt;tuple&gt;

#if defined(VARIANT1)
using accepted_types = std::tuple &lt;std::string, std::set&lt;int&gt;&gt;;
#elif defined(VARIANT2)
using accepted_types = std::tuple &lt;std::map&lt;int,int&gt;, std::vector&lt;int&gt;&gt;;
#endif

Then we need a has_type type trait to check if one type is included in a std::tuple based type (see link to that answer for the full description):

#include &lt;type_traits&gt;

template &lt;typename T, typename Tuple&gt;
struct has_type;

template &lt;typename T&gt;
struct has_type&lt;T, std::tuple&lt;&gt;&gt; : std::false_type {};

template &lt;typename T, typename U, typename... Ts&gt;
struct has_type&lt;T, std::tuple&lt;U, Ts...&gt;&gt; : has_type&lt;T, std::tuple&lt;Ts...&gt;&gt; {};

template &lt;typename T, typename... Ts&gt;
struct has_type&lt;T, std::tuple&lt;T, Ts...&gt;&gt; : std::true_type {};

template&lt;class T, class V&gt;
static constexpr bool has_type_v = has_type&lt;T, V&gt;::value;

Then enable the template only for those types included in accepted_types:

template &lt;typename VarType,
          typename = std::enable_if_t&lt;has_type_v&lt;VarType, accepted_types&gt;&gt;&gt;
class CMyClass {
    
};

Demo

答案3

得分: 0

**免责声明:** 此答案需要C++20,并且是在问题添加C++14要求信息之前发布的。

您可以定义一个类模板,该类模板继承自`std::bool_constant`、`std::true_type`或`std::false_type`,具体取决于预处理器定义,可能需要使用特化。这允许您使用类模板创建一个概念,用于限制与您的类模板一起使用的类型参数。

```cpp
template<class T, class ... Args>
inline constexpr bool IsAnyOf_v = (std::is_same_v<T, Args> || ...);

template<class T>
struct IsAllowed;

#ifdef VARIANT1

// 你可以在定义中提供一切...
template<class T>
struct IsAllowedType : std::bool_constant<IsAnyOf_v<T, int, char>> {};

#elif defined(VARIANT2)

// ...或提供默认值,并为特定类型进行特化
template<class T>
struct IsAllowedType : std::false_type {};
template<>
struct IsAllowedType<unsigned> : std::true_type {};

#else
#error 未知的变体
#endif

template<class T>
concept AllowedType = IsAllowedType<T>::value;

...

template<AllowedType VarTypes>
class CMyClass
{
   // 做一些事情
};

<details>
<summary>英文:</summary>

**Disclaimer:** This answer requires C++20 and was posted before the information about the C++14 requirement was added to the question.

You could define a class template that inherits from `std::bool_constant`, `std::true_type` or `std::false_type` depending on the preprocessor definitions, possibly using specializations. This allows you to use the class template to create a concept for restricting the type arguments used with your class template.

template<class T, class ... Args>
inline constexpr bool IsAnyOf_v = (std::is_same_v<T, Args> || ...);

template<class T>
struct IsAllowed;

#ifdef VARIANT1

// you could provide everything in the definition...
template<class T>
struct IsAllowedType : std::bool_constant<IsAnyOf_v<T, int, char>> {};

#elif defined(VARIANT2)

// ...or provide a default and specialize for specific types
template<class T>
struct IsAllowedType : std::false_type {};
template<>
struct IsAllowedType<unsigned> : std::true_type {};

#else
#error unknown variant
#endif

template<class T>
concept AllowedType = IsAllowedType<T>::value;

...

template<AllowedType VarTypes>
class CMyClass
{
// do something
};


</details>



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

发表评论

匿名网友

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

确定