【问题标题】:Need guidance on sub-templating method in C++需要 C++ 中子模板方法的指导
【发布时间】:2021-05-03 22:46:31
【问题描述】:

我知道了:

#include<iostream>
#include <functional>
using namespace std;

template<class T>
class A
{
public:
    template<class S>
    function<S(T)> transform;
};

int main()
{
    obiekt.transform = [=] (int element) { return (float)element; };
}

如何使转换函数具有第二种类型的通用性?我不是在问如何向A 添加第二种类型,例如A&lt;int, float&gt;。我知道该怎么做。

【问题讨论】:

  • 如果这是合法的,则意味着A&lt;int&gt; 对象包含function&lt;void(int)&gt; 成员对象、不同的function&lt;int(int)&gt; 成员对象、不同的function&lt;std::vector&lt;char&gt;(int)&gt; 成员对象等。

标签: c++ templates generics lambda


【解决方案1】:

为此,您将需要某种形式的类型擦除。你看,选择一个特定的 std::function 将包含什么 lambda 是一个运行时决定。您无法在运行时决定返回类型是什么。

要允许任何返回类型,您可能需要std::any

#include <any>

template<class T>
class A
{
public:
    function<any(T)> transform;
};

Live working example

如果您知道所有可能的类型 transform 可能会返回,则更适合使用变体:

#include <variant>

template<class T>
class A
{
public:
    using return_type = variant<int, float, string>;
    function<return_type(T)> transform;
};

Live working example

这两个 sn-ps 都可以让你的 main 编译。


当然,您也可以在编译时决定一切,甚至是 lambda 类型。这将允许A 类型的单个模板参数,同时允许任何返回类型:

template<class T>
class A
{
public:
    A(T t) : transform{t} {}
    T transform;
};

int main() {
    // The compiler will deduce something like A<lamda#1-type>
    A obiekt{
        [=] (int element) { return (float)element; }
    };

    float a = obiekt.transform(1);
}

Live working example

我在第三个示例中提出的建议是删除类型擦除并简单地将模板参数用于整个 lambda 类型。 lambda 有自己的类型,每个 lambda 都不同。 std::function 是围绕任何可调用类型的类型擦除包装器,就像 std::any 但定义了 operator()

【讨论】:

    猜你喜欢
    • 2020-09-11
    • 2011-01-02
    • 2022-01-18
    • 2011-07-22
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 2022-06-30
    相关资源
    最近更新 更多