我正在尝试使用模板化的参数执行一个非常简单的抽象工厂,并且收到一个我无法理解的错误。
核心问题是,在模板之外,变量类型接受其联合的任何成员,但是在模板内部,这种推论似乎失败了。在我的构造中找到导致这种情况的错误。
最小产生代码如下:只需删除模板,就可以编译
code 1006
但是,如所写,它会吐出编译错误
class A{};
class B{};
using AB = std::variant<A,B>;
template <class T1, class T2>
class Parent
{
};
class Child : public Parent<A,B>
{
public:
static Parent<A,B>* build(){ return new Child(); }
};
template <class T1, class T2>
using Fn = std::function<Parent<T1,T2> *(void)>;
using ParentFn = Fn<AB,AB>;
int main()
{
// in a factory, we might say
// map<string, ParentFn> m; m["key"] = &Child::build;
// but for MRE I'll just do assignment
ParentFn tmp = &Child::build; // does just fine without templates, crashes horribly with
return 0;
}
我认为问题不是an lvalue/rvalue issue like this question,因为所引用的方法是静态的(但我们也可以将其拔出并强制为左值,而无需解决此错误)。 GCC is known to have some bugs with aliases,但我在这里看不到它们的相关性,因为我认为它们与变量无关。我正在使用g ++-7.1,-std = c ++ 17
在请求类型为main.cpp:32:24: error: conversion from ‘Parent<A, B>* (*)()’ to non-scalar type ‘ParentFn {aka std::function<Parent<std::variant<A, B>, std::variant<A, B> >*()>}’ requested
ParentFn tmp = &Child::build; // does just fine without templates, crashes horribly with
的情况下,编译器为什么不能接受类型A
?这不是变体的全部内容吗?例如,variant<A,B>
或AB ab = A();
都有效,尽管这可能只是AB ab = B();
运算符的聪明重载?
我是否滥用变量,std :: function,模板,别名或以上所有内容?
为证明问题与模板有关,没有模板的代码编译为:
=
我认为std变体可以替代任何一种单独类型的依据是微不足道的测试
class Parent
{
};
class Child : public Parent
{
public:
static Parent* build(){ return new Child(); }
};
using Fn = std::function<Parent *(void)>;
using ParentFn = Fn;
int main()
{
ParentFn tmp = &Child::build; // does just fine without templates, crashes horribly with
return 0;
}
两者都可以接受。
答案 0 :(得分:2)
模糊化代码,我认为您要尝试执行的操作归结为尝试以下操作。
作品
#include <variant>
class A{};
class B{};
using AB = std::variant<A,B>;
AB * Foo();
typedef AB*(*Fn)();
int main()
{
Fn f = &Foo;
}
不起作用
#include <variant>
class A{};
class B{};
using AB = std::variant<A,B>;
AB * Foo();
typedef A*(*Fn)();
int main()
{
Fn f = &Foo;
}
错误:从'AB *()()'{aka'std :: variant ()()'}到'Fn'{aka'A (*)()'} [-fpermissive]
如果您想进一步减少它,则尝试将std::variant<A,B> *
转换为A*
,这将不起作用。
实际上,您甚至无法将A*
转换为std::variant<A,B> *
。唯一允许的转换是A
到std::variant<A,B>
或B
到std::variant<A,B>