C++14 auto lambda 可以接受 Obj<std::tuple<void> > -- 但模板函数不能?
C++14 auto lambda can accept Obj<std::tuple<void> > -- but template functions cannot?
下面的程序完全演示了我遇到的问题。
首先,我从一个使用其他类型的分组定义的对象开始,我开始使用 std::tuple<> 来管理分组。
template <typename> class object;
template <typename... Rs> class object<std::tuple<Rs...> > {
};
我打算 这些对象能够具有 void
类型分散在 "pack" 中。我已经知道无法 "instantiate" 这种类型的元组
(参见 Void type in std::tuple)
我想传递这些对象,也许 copy/move 它们... none 它们的数据成员 是 这些类型的元组。事实上,我可以使用上面的空对象定义重现该问题。
我可以让它工作,使用类似的东西:
template <typename... Rs> struct TGrp {};
template <typename> class object;
template <typename... Rs> class object<TGrp<Rs...> > {
};
这些类型的 "grouping" 结构在可变递归中经常使用,它们永远不会得到 created/used。只是对模板参数进行分组。
不过我"want"的签名'object'要组成"user expected"types/names.
基本上,当 std::tuple
用于 "group" 时,我正在试验 任何可能的 传递这些对象之一的方法,并且只能找到一种方式:自动 lambda。
谁能解释一下:
为什么 "auto" lambda 可以用于此?
关于延迟模板推导的事情?比如 b/w "auto" 和 "decltype(auto)"?
如何"design"函数参数接受这些对象之一。
-- 感谢大家对这个怪事的任何见解
示例:
#include <tuple>
#include <iostream>
#define GRP std::tuple // IF 'tuple' used: compile error where noted below
//#define GRP TGrp // if THIS is used: all works, and TGrp() is never constructed
// Grouping mechanism
template <typename... Ts> struct TGrp {
TGrp() {
std::cout << "Never printed message\n";
}
};
// MAIN OBJECT (empty for forum question)
template <typename> class object;
template <typename... Rs> class object<GRP<Rs...> > {
};
// Regular function (does NOT work)
void takeobj(object<GRP<void> >& obj) { (void)obj; }
// Lambda - taking anything... (only thing I could make WORK)
auto takeobj_lambda = [](auto obj) { (void)obj; };
// Template func - taking anything (does NOT work)
template <typename T> void takeobj_templ_norm(T obj) { (void)obj; }
template <typename T> void takeobj_templ_clref(const T& obj) { (void)obj; }
template <typename T> void takeobj_templ_lref(T& obj) { (void)obj; }
template <typename T> void takeobj_templ_rref(T&& obj) { (void)obj; }
int main()
{
object<GRP<void> > oval;
//takeobj(oval); // <-- causes compile error
takeobj_lambda(oval); // works
//takeobj_templ_norm(oval); // <-- also error
//takeobj_templ_clref(oval); // <-- also error
//takeobj_templ_lref(oval); // <-- also error
//takeobj_templ_rref(oval); // <-- also error
return 0;
}
编辑:添加经过修剪的复制品:
#include <tuple>
// MAIN OBJECT (empty for forum question)
template <typename> class object;
template <typename... Rs> class object<std::tuple<Rs...> > {
};
// Regular function (does NOT work)
void takeobj(object<std::tuple<void> >& obj) { (void)obj; }
// Lambda - taking anything... (only thing I could make WORK)
auto takeobj_lambda = [](auto obj) { (void)obj; };
int main()
{
object<std::tuple<void> > oval;
//takeobj(oval); // <-- causes compile error
takeobj_lambda(oval); // works
return 0;
}
std::tuple<void>
是 object<std::tuple<void>>
的 关联 class,因此在执行参数相关查找的非限定调用中, std::tuple<void>
被实例化以查找可能已内联定义的任何 friend
函数。此实例化导致错误。
如果被调用的东西没有命名函数或函数模板,则不执行依赖于参数的查找;因此使用 lambda 是可行的——takeobj_lambda
是一个对象。
如果您使用限定调用 (::takeobj(oval)
) 或括号 takeobj
((takeobj)(oval)
),则代码可以编译。这两个都禁用 ADL。
下面的程序完全演示了我遇到的问题。
首先,我从一个使用其他类型的分组定义的对象开始,我开始使用 std::tuple<> 来管理分组。
template <typename> class object;
template <typename... Rs> class object<std::tuple<Rs...> > {
};
我打算 这些对象能够具有 void
类型分散在 "pack" 中。我已经知道无法 "instantiate" 这种类型的元组
(参见 Void type in std::tuple)
我想传递这些对象,也许 copy/move 它们... none 它们的数据成员 是 这些类型的元组。事实上,我可以使用上面的空对象定义重现该问题。
我可以让它工作,使用类似的东西:
template <typename... Rs> struct TGrp {};
template <typename> class object;
template <typename... Rs> class object<TGrp<Rs...> > {
};
这些类型的 "grouping" 结构在可变递归中经常使用,它们永远不会得到 created/used。只是对模板参数进行分组。
不过我"want"的签名'object'要组成"user expected"types/names.
基本上,当 std::tuple
用于 "group" 时,我正在试验 任何可能的 传递这些对象之一的方法,并且只能找到一种方式:自动 lambda。
谁能解释一下:
为什么 "auto" lambda 可以用于此?
关于延迟模板推导的事情?比如 b/w "auto" 和 "decltype(auto)"?
如何"design"函数参数接受这些对象之一。
-- 感谢大家对这个怪事的任何见解
示例:
#include <tuple>
#include <iostream>
#define GRP std::tuple // IF 'tuple' used: compile error where noted below
//#define GRP TGrp // if THIS is used: all works, and TGrp() is never constructed
// Grouping mechanism
template <typename... Ts> struct TGrp {
TGrp() {
std::cout << "Never printed message\n";
}
};
// MAIN OBJECT (empty for forum question)
template <typename> class object;
template <typename... Rs> class object<GRP<Rs...> > {
};
// Regular function (does NOT work)
void takeobj(object<GRP<void> >& obj) { (void)obj; }
// Lambda - taking anything... (only thing I could make WORK)
auto takeobj_lambda = [](auto obj) { (void)obj; };
// Template func - taking anything (does NOT work)
template <typename T> void takeobj_templ_norm(T obj) { (void)obj; }
template <typename T> void takeobj_templ_clref(const T& obj) { (void)obj; }
template <typename T> void takeobj_templ_lref(T& obj) { (void)obj; }
template <typename T> void takeobj_templ_rref(T&& obj) { (void)obj; }
int main()
{
object<GRP<void> > oval;
//takeobj(oval); // <-- causes compile error
takeobj_lambda(oval); // works
//takeobj_templ_norm(oval); // <-- also error
//takeobj_templ_clref(oval); // <-- also error
//takeobj_templ_lref(oval); // <-- also error
//takeobj_templ_rref(oval); // <-- also error
return 0;
}
编辑:添加经过修剪的复制品:
#include <tuple>
// MAIN OBJECT (empty for forum question)
template <typename> class object;
template <typename... Rs> class object<std::tuple<Rs...> > {
};
// Regular function (does NOT work)
void takeobj(object<std::tuple<void> >& obj) { (void)obj; }
// Lambda - taking anything... (only thing I could make WORK)
auto takeobj_lambda = [](auto obj) { (void)obj; };
int main()
{
object<std::tuple<void> > oval;
//takeobj(oval); // <-- causes compile error
takeobj_lambda(oval); // works
return 0;
}
std::tuple<void>
是 object<std::tuple<void>>
的 关联 class,因此在执行参数相关查找的非限定调用中, std::tuple<void>
被实例化以查找可能已内联定义的任何 friend
函数。此实例化导致错误。
如果被调用的东西没有命名函数或函数模板,则不执行依赖于参数的查找;因此使用 lambda 是可行的——takeobj_lambda
是一个对象。
如果您使用限定调用 (::takeobj(oval)
) 或括号 takeobj
((takeobj)(oval)
),则代码可以编译。这两个都禁用 ADL。