调用模板类型的方法

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

Calling methods for template types

问题

以下是翻译的代码部分:

假设我有这样一个类:

     template<typename Type>
     struct Policy {
    	 virtual bool cause() = 0;
    	 virtual void implement(std::shared_ptr<Type> type) = 0;
     };

我想创建一个如下所示的方法:

     template<template<typename> typename TPolicy, typename TObj>
     void integrate(TPolicy<TObj>&& policy, std::shared_ptr<TObj> val) {
    	if (policy.cause())
    		policy.implement(val);
     }

这个方法必须接受一个策略参数和要应用该策略的对象。

1. 有没有一种方法可以实现`integrate()`方法,使其也能接受指针类型的策略?例如`Policy<T>*`,`shared_ptr<Policy<T>>`?因为这个实现使用了不支持指针类型的`.`运算符。

2. 如何正确检查`TPolicy`实际上是从类`Policy<T>`派生的?
英文:

Suppose I have a class like this:

 template&lt;typename Type&gt;
 struct Policy {
	 virtual bool cause() = 0;
	 virtual void implement(std::shared_ptr&lt;Type&gt; type) = 0;
 };

I want to create a method as follows:

 template&lt;template&lt;typename&gt; typename TPolicy, typename TObj&gt;
 void integrate(TPolicy&lt;TObj&gt;&amp;&amp; policy, std::shared_ptr&lt;TObj&gt; val) {
	if (policy.cause())
		policy.implement(val);
 }

The method has to take in a policy parameter and the object on which to apply this policy.

  1. Is there a way to implement the method integrate() in a way that it will also accept pointer types as Policies? For instance Policy&lt;T&gt;*, shared_ptr&lt;Policy&lt;T&gt;&gt;? Because this implementation uses the . operator that is not supported by pointer types.

  2. How to properly check that TPolicy actually derives from the class Policy&lt;T&gt;?

答案1

得分: 1

以下是您要翻译的内容:

基本上,您正在寻找<type_traits>中的std::is_base_of_v

然后,您需要使用编译时特性来检查您的函数是否应该编译或不编译。根据您的编译器版本,有各种技术可以实现这一点(通常情况下,较新版本的C++更容易实现)。

在线示例在这里(https://onlinegdb.com/VEaScpqbF)。
源代码如下:

#include <memory>
#include <type_traits>

class Policy
{
};

class MyPolicy :
    public Policy
{
};

class NotAPolicy
{
};

// is_base_of_v足够了,我通常为了可读性而创建一个constexpr函数
// 有时候一个检查需要多个特性检查
// 这也允许进行编译时检查(参见main函数)
template<typename policy_t>
static constexpr bool is_policy()
{
    return std::is_base_of_v<Policy, policy_t>;
}

//C++20引入了概念(concepts),用于更可读的元编程技术
template<typename policy_t>
concept IsPolicy = is_policy<policy_t>();

// 对于C++17及更低版本,使用std::enable_if SFINAE
// 返回一个“错误类型”(不存在的类型)将导致函数无法编译
// 注意:我稍微简化了您的函数签名,以展示原理
template<typename policy_t>
auto integrate_cpp17(policy_t&& policy) 
    -> std::enable_if_t<is_policy<policy_t>(), void> // 如果有策略,返回void,否则返回“错误类型”
{
}

void integrate_cpp20(IsPolicy auto&& policy)
{
}

int main()
{
    static_assert(is_policy<MyPolicy>());
    static_assert(!is_policy<NotAPolicy>());

    integrate_cpp17(MyPolicy{});
    integrate_cpp17(NotAPolicy{}); // 不会编译,正如预期的那样

    integrate_cpp20(MyPolicy{});
    integrate_cpp20(NotAPolicy{}); // 不会编译,正如预期的那样

    return 0;
}

请注意,我只翻译了代码部分,没有添加其他内容。

英文:

Basically you are looking for std::is_base_of_v from &lt;type_traits&gt;.

Then you need to use that compile time trait to check if your function should compile or not. Various techniques exist to do that depending on your compiler version (in general the newer versions of C++ make this more easy).

Live example here (https://onlinegdb.com/VEaScpqbF).
And source code :

#include &lt;memory&gt;
#include &lt;type_traits&gt;

class Policy
{
};

class MyPolicy :
    public Policy
{
};

class NotAPolicy
{
};

// is_base_of_v is enough, I usually make 
// a constepr function for readability
// and sometimes a check requires multiple trait checks 
// it also allows for compile time check (see main)
template&lt;typename policy_t&gt;
static constexpr bool is_policy()
{
    return std::is_base_of_v&lt;Policy, policy_t&gt;;
}

//C++20 has concepts for  more readable meta (template) programming techniques
template&lt;typename policy_t&gt;
concept IsPolicy = is_policy&lt;policy_t&gt;();

// for C++17 and lower, use std::enable_if SFINAE
// returning an &quot;error type&quot; (non existent type) will result in function
// not being compilable
// NOTE : simplified your signature a bit, to show the principle 
template&lt;typename policy_t&gt;
auto integrate_cpp17(policy_t&amp;&amp; policy) 
    -&gt; std::enable_if_t&lt;is_policy&lt;policy_t&gt;(),void&gt; // return type is void if there is a policy, an &quot;error type&quot; otherwise 
{
}

void integrate_cpp20(IsPolicy auto&amp;&amp; policy)
{
}

int main()
{
    static_assert(is_policy&lt;MyPolicy&gt;());
    static_assert(!is_policy&lt;NotAPolicy&gt;());

    integrate_cpp17(MyPolicy{});
    integrate_cpp17(NotAPolicy{}); // does not compile as intended

    integrate_cpp20(MyPolicy{});
    integrate_cpp20(NotAPolicy{}); // does not compile as intended


    return 0;
}

huangapple
  • 本文由 发表于 2023年6月1日 10:41:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76378352.html
匿名

发表评论

匿名网友

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

确定