【问题标题】:Cannot deduce type of a templated class member [duplicate]无法推断模板类成员的类型 [重复]
【发布时间】:2020-01-07 12:13:01
【问题描述】:

受到This 示例的启发,即受到这段特定代码的启发

// ...
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
// ...
std::visit(overloaded {
    [](auto arg) { std::cout << arg << ' '; },
    [](double arg) { std::cout << std::fixed << arg << ' '; },
    [](const std::string& arg) { std::cout << std::quoted(arg) << ' '; },
}, v);

...我试图定义一个overloaded 类型的类成员,但偶然发现了一些困难,我认为(但不完全确定)这是由于编译器无法推断出模板的参数造成的。

template<class ...Ts>
struct overloaded : Ts... {
    using Ts::operator()...;
    constexpr overloaded(Ts... ts) : Ts(ts)... {}
};

struct as{};

class phil_t {
    int i;
    overloaded o { [&](as&) {cout << i << "as"; } }; // <-- HERE
};

这是我收到的输出:

../../variant.hpp:21:5: error: invalid use of template-name ‘overloaded’ without an argument list
     overloaded o { [&](as&) {cout << i << "as"; } };
     ^~~~~~~~~~

很明显,当我使用相同的方法来实例化不在类中的对象时,一切都运行得很顺利。

void varnt() {
    int i = 42;
    auto o = overloaded( [&](as&) {cout << i << "as"; } );
}

我们将不胜感激任何建议、解释或一些解决方法的提示。

谢谢。

【问题讨论】:

  • @Evg 不完全是。它帮助我理解“为什么”,而不是“如何”。不过还是谢谢你:)
  • 似乎没有简单的方法可以打破循环依赖。一种可能的解决方案是use type-erasure。是否实用,我不确定。

标签: c++ templates type-deduction


【解决方案1】:

你不能有一个不是某种特定类型的成员变量,这是你在phil_t 中尝试做的,因为overloaded 指的是模板而不是类型。

class phil_t;

auto make_overloaded(phil_t& pt) {
    return  overloaded { [&](auto & x) { /* do something with x */ } };
}

class phil_t {
    int i;
    decltype(make_overloaded(std::declval<phil_t&>())) o = make_overloaded(*this);  // <-- HERE
};

现场示例here

这段代码的问题是你想在你的lambda中使用phil_t,所以你不能使用我的方法,因为phil_t在调用make_overload时是不完整的。

感谢@Evg:这是一个使用类型擦除的解决方案,比上面的代码效果更好:

#include <iostream>
#include <any>

template<class ...Ts>
struct overloaded : Ts... {
    using Ts::operator()...;
    constexpr overloaded(Ts... ts) : Ts(ts)... {}
};

struct as1 {};
struct as2 {};

class phil_t {
private:
    auto make_overloaded() {
        return overloaded{
            [&](as1& x) { std::cout << "1: " << i << std::endl; },
            [&](as2& x) { std::cout << "2: " << i << std::endl; }
        };
    }

public:
    phil_t() : o(make_overloaded()) {}

    template<class As>
    void foo(As as) {
        std::any_cast<decltype(make_overloaded())>(o)(as);
    }

private:
    int i = 42;
    std::any o;
};

int main() {
    phil_t p;
    p.foo(as1{});
    p.foo(as2{});
}

第二个 sn-p 的所有学分都转到 @Evg !

现场示例here

【讨论】:

  • 注意 OP 的 lambda 中的 [&amp;]i
  • @Evg 啊,对,谢谢。
  • 如果您尝试在 lambda 中实际使用 pt,您将收到“不完整类型”错误。
  • 对,刚刚想通了……
  • 我认为这是一个先有鸡还是先有蛋的问题。知道如何解决吗?
猜你喜欢
  • 2021-03-04
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多