是什么原因导致它无法编译?它是声明签名还是在函数本身的实现中
What is causing this to fail to compile? Is it the declaration signature or is it within the implementation of the function itself?
我正在处理Component
类的成员函数Component::connect()
。Component
是我库中所有其他组件类型的抽象基类。
我现在正在修改这个方法,使用变分函数模板和SFINAE来允许未知的多个输入到这个函数中。。。所有输入都必须派生自Component
类型。
我对它的声明和实现的语法有问题。。。我尝试了各种各样的方法,但却遇到了各种编译器错误。这可能与参数包扩展有关,或者我如何尝试在其签名中使用SFINAE有关。
这是我正在处理的类和函数的当前签名…
class Component {
protected:
std::string id_ = "";
std::list<std::shared_ptr<Component>> components_;
explicit Component(const std::string& id) : id_{ id } {}
public:
virtual ~Component() {}
std::string& id() { return id_; }
// Trying to use both Variadic Function Template and SFINAE for this function!
// I may eventually remove this from here and move it to another class using CRTP...
template<typename ... Args, std::enable_if_t <std::is_class<Args...>{}, Component> = 0 >
void connect(Args&& ...args) {
for (auto& l : components_) {
if (args->id_ == l->id()) {
std::cout << "Component " << (args->id_) << " already exists in " << id_ << "!n";
return;
}
}
components_.push_back( std::make_shared<Component>( args... ) );
std::cout << "Successfully connected " << args->id() << " to " << id_ << "n";
}
virtual std::list<std::shared_ptr<Component>> myConnections() { return components_; }
virtual void propagate() {};
};
使用C++17在Visual Studio 2017中成功编译此文件的正确语法是什么?我正在尝试使用SFINAE来利用这两个变分函数模板。
编辑
在我更改签名之前,从Component
派生的派生类(如Wire
(我可以这样使用它们:
Wire w1, w2, w3, w4;
w1.connect(&w2);
w1.connect(&w3);
w1.connect(&w4);
w2.connect(&w3);
w2.connect(&w4);
我想使用相同的功能,但以这种方式:
w1.connect(&w2, &w3, &w4);
这就是我想要使用变分函数模板的原因,也是我想要使用SFINAE来确保传递到::connect()
中的任何类型(其中所有派生类都可以使用它(实际上都是从Component
派生的!
不确定你到底想要什么(没有完整的例子更难(,但。。。
所有输入都必须从组件类型派生。
所以,如果我理解正确(并且给你标记了C++17,所以你可以使用折叠(,该方法的签名应该是
template <typename ... Args,
std::enable_if_t<(... && std::is_base_of<Component, Args>{}),
int> = 0>
void connect (Args && ... args)
或者
template <typename ... Args>
std::enable_if_t<(... && std::is_base_of<Component, Args>{})>
connect (Args && ... args)
我对它的声明和实现的语法有问题。。。
关于实现,我认为更大的问题是周期;也许你可以试试
for ( auto & l : components_ )
{
std::string aid;
if ( true == ( ... || (args->id_ == l->id()
? (aid = args->id_, true)
: false) ) )
{
std::cout << "Component " << aid
<< " already exists in " << id_ << "!n";
return;
}
}
或者
for ( auto & l : components_ )
{
std::string aid;
( ... , (args->id_ == l->id() ? aid = args->id_ : args->id_) );
if ( false == aid.empty() )
{
std::cout << "Component " << aid
<< " already exists in " << id_ << "!n";
return;
}
}
或者类似的东西。
但是关于
std::cout << "Successfully connected " << args->id() << " to " << id_ << "n";
坦率地说。。。我不知道。
error: expression contains unexpanded parameter pack 'args' if (args->id_ == l->id()) {
您可以将connect()
拆分为两个函数来处理当前未扩展的参数包。一个函数进行检查和连接,另一个函数使用折叠表达式:
template<typename T> // connect one only
void connect(T&& arg) {
static_assert(std::is_base_of_v<Component, std::remove_reference_t<T>>,
"Must be based on Component");
for (auto& l : components_) {
if (arg.id_ == l->id()) {
std::cout << "Component " << arg.id_ << " already in " << id_ << "n";
return;
}
}
components_.push_back( std::make_shared<Component>( std::forward<T>(arg) ) );
std::cout << "Successfully connected " << arg.id() << " to " << id_ << "n";
}
template<typename... Args> // folding
void connect(Args&& ...args) {
(connect(std::forward<Args>(args)), ...);
}
连接会这样做:
w1.connect(w2, w3, w4);
演示(使用您问题的旧修订版中的部分(
相关文章:
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 分段 排序函数实现中的错误
- 无法去函数实现 vim
- C++ 20 中的运算符 == 和 <=> 应该作为成员还是自由函数实现?
- 为什么在这种情况下不调用我的虚拟函数实现?
- 我能否通过将函数实现为类对象方法来避免使用互斥锁
- 嵌套的模板结构构造函数实现
- C++接口的工厂函数实现
- 链表中的递归长度函数实现
- 我可以期望某些 STL 函数实现是可自动矢量化的吗?
- 如何将深拷贝构造函数实现到链表中?
- 虚拟 CTOR 的克隆函数实现是否有问题
- 没有捕获列表的 lambda 通常作为普通函数实现吗?
- C++二叉树打印函数实现
- C++:默认构造函数实现
- C++派生类中的纯虚函数实现
- 决定放置函数实现的位置
- 强制实施纯虚函数实现,可能使用不同的参数类型
- 如何让成员函数实现依赖于类的模板参数?
- 我们如何将Ostream函数作为类的成员函数实现,而不是作为朋友函数,以便我可以用作虚拟函数