STD ::功能,字面类型和模板
std::function, literal types and templates
我正在从事C 17项目,其中包括这些定义(当然是在我的名称空间中(:
using CppFunction = std::function<int(StatePtr&)>;
template<typename T>
using CppMethod = std::function<int(T*, StatePtr&)>;
现在我声明了一些功能:
template<typename... Targs, typename F>
constexpr CppFunction CppFunctionNative(F func);
template<typename... Targs, typename F, typename T = (deducing class from F here) >
constexpr CppMethod<T> CppMethodNative(F func);
令我惊讶的是,第一个声明会导致编译器错误 Constexpr function's return type is not a literal type
,但第二起正常工作。
为什么会发生这种情况?这与第二个功能的返回类型是模板有关吗?
upd:简化的独立示例:
#include <functional>
using CppFunction = std::function<int(int&)>;
template<typename T>
using CppMethod = std::function<int(T*, int&)>;
// Clang will complain
template<typename F>
constexpr CppFunction CppFunctionNative(F func) {};
// Clang will not complain
template<typename F, typename T = /*(deducing class from F here)*/char >
constexpr CppMethod<T> CppMethodNative(F func) {};
// main() function doesn't matter
int main() {
CppFunctionNative(0);
CppMethodNative(0);
return 0;
};
有趣的是,在线gdb和Offline GCC 8.3.0并没有抱怨,但是我的clang 8会。
令我惊讶的是,第一个声明原因是编译器错误constexpr函数的返回类型不是字面类型,但第二起工作正好。
为什么会发生这种情况?这与第二个功能的返回类型是模板有关吗?
是。在第一种情况下,编译器可以证明std::function
的特定专业不是字面类型。
在第二种情况下,它必须知道T
才能知道std::function
的特定专业化是否是字面类型。
template<class T>
struct example {
virtual T get() const {return {};}
~example() {}
};
template<>
struct example<int> {};
#if 0
template<class F>
constexpr example<double> test( F ) { return {}; }
#endif
template<class T, class F>
constexpr example<T> test2( F ) { return {}; }
实例示例
test
是非法的;test2
很好。实际上,test2<int>( 3.14 )
是法律constexpr
调用。
现在,std::function
具有没有这样的专业化,但这不是编译器证明的要求;一般而言,这样做需要解决停止问题,这是C 标准试图避免要求编译器做的事情。
正如@maxlanghof所述,这种错误导致"不良形式,无需诊断"。程序。编译器不会被迫检测到您的constexpr
函数不能为constexpr
,但是如果您执行编译器可以免费执行任何操作,包括生成错误消息(或更糟糕的消息(。
因此,GCC省略错误并不是错误的,并且发出错误并没有错。从某种意义上说,Clang的误差排放比GCC的遗漏更高。
编辑:yakk的答案更完整 - 当然必须考虑std::function
专业的理论可能性!
constexpr
的意思是"至少有一组参数会产生恒定表达式"。如果没有这样的论点,则该程序是不形式的,无需诊断。这意味着是否完全忽略了此问题,无论它仅在实例化时还是已经在声明中吠叫。
clang
显然很聪明/渴望,足以意识到具有非文字返回类型的功能模板永远不可能是constexpr
。gcc
似乎并没有打扰检查此问题 - 不需要。但是您的程序仍然错了-std::function
不是字面类型,因此永远不能从constexpr
函数中返回。
- 错误:在尝试检测 std::cout 是否<< t 时,功能强制转换为数组类型;有效
- 对于非常量指针类型的参数,未调用具有常量指针模板类型参数的功能
- C++从成员类型中扣除类型的功能模板?
- 这种错误的原因是什么:将"功能"重新定义为不同类型的符号
- 模板功能:根据类型名称进行转换
- 如何在同一个模板功能上专门化几种类型?
- 错误:未知类型名称"功能跟踪"
- 我对C 中共享指针列表进行排序的功能未完成类型
- 共享_ptr中多功能数组的类型是什么
- 确定功能主体中的返回类型
- 返回类型不可知模板类成员功能
- 类型推论模板功能返回类型
- C 功能模板指定第二个模板参数类型
- 为什么指定数据类型而不是构造功能参数?C
- C 尝试使用模板输出功能来显示不同类型的数据
- 为什么BOOST :: HANA :: EXAREMIS ::键入实验功能?类型列表的棘手是什么
- 将多种类型传递给STD ::功能C
- C 中此功能的返回类型的含义
- C++ 使用包含不同类型功能对象的基和派生类的 Reactor
- 请求从非标量类型转换为非标量类型(功能)