替换失败不是错误。这是一种C ++编程技术,允许模板验证有关其模板参数的属性,从而允许在某些类型的对象可用时使用不同的特化。
示例 许多以下阶层的消费者 A类{ 双a; 无效转储(){ std::ofstream ooo("dump.txt");哦<< A.a << "\n"; ooo.close(); } }; wi...
基于用户定义的输入类型类别的C++函数调度(C++11/14友好)
我想根据用户定义的输入类型“标签”来调度函数。例如,我定义了一个名为 SomeSpecificObjectType 的标签,并在 Object 类中将此类标记为
GCC 14 中的 C++ 模糊成员函数模板解析与非成员函数模板解析,但在之前的 GCC 版本中没有解析
以下代码可以在 GCC 13 及更早版本中正常编译,但 GCC 14.1 会产生“模糊重载”错误。这是编译器还是代码问题,更务实的是,我可以让 co...
我有几个重载函数,如下所示: 模板 结构点{ std::enable_if_t,T> x,y; }; //...
我有以下代码,它接受一个值并返回 0 和该值之间的随机值: 模板 类型名 std::enable_if::value>::type
如何使 `if constexpr` 变得对 SFINAE 友好?
我有一个使用“经典”SFINAE 的代码。 template auto power(M const& elem) -> decltype(std::norm(elem)) { return std::norm(elem); } 模板 我有一个使用“经典”SFINAE 的代码。 template<class M> auto power(M const& elem) -> decltype(std::norm(elem)) { return std::norm(elem); } template<class M, class = std::enable_if_t<(M::rank::value >= 1)>> auto power(M const& array) { return accumulate(begin(array), end(array), 0.0, [](auto const& alpha, auto const& omega) { return alpha + power(omega); }); } 这是一个递归(跨维度或等级)“幂”函数,通过计算较低维度子元素的幂,最终给出元素的平方和。 现代 C++ 鼓励使用 if constexpr 以避免使用 SFINAE,如下所示。 template<class M> auto power(M const& array) { if constexpr(M::rank::value >= 1) { return accumulate(begin(array), end(array), 0.0, [](auto const& alpha, auto const& omega) { return alpha + power(omega); }); } else { return std::norm(array); } } 问题在于,if constexpr中的表达式似乎首先必须是有效的表达式。 元素没有名为 rank 的成员类型,因此会出现编译错误。 如果表达式无效,是否有技巧可以使 if constexpr 谓词? C++20 及更新版本: if constexpr (requires{requires std::bool_constant</*condition*/>::value;}) 还有一个不太详细的选项: if constexpr (requires{requires /*condition*/;}) 但是后者更糟糕,因为如果编译时不知道条件,它会导致硬错误,而前者只是返回 false。 前者在标准库中使用(另请参阅在嵌套需求中,为什么使用requires bool_constant<X>::value;而不是requires X;?)。 C++17: 使用检测惯用语: #include <type_traits> namespace detail { template <typename ...P> struct void_type {using type = void;}; template <typename DummyVoid, template <typename...> typename A, typename ...B> struct is_detected : std::false_type {}; template <template <typename...> typename A, typename ...B> struct is_detected<typename void_type<A<B...>>::type, A, B...> : std::true_type {}; } template <template <typename...> typename A, typename ...B> inline constexpr bool is_detected = detail::is_detected<void, A, B...>::value; 然后: template <typename M> using CheckRank = std::enable_if_t<M::rank::value >= 1>; if constexpr (is_detected<CheckRank, M>)
我有一个使用“经典”SFINAE 的代码。 template auto power(M const& elem) -> decltype(std::norm(elem)) { return std::norm(elem); } 模板 我有一个使用“经典”SFINAE 的代码。 template<class M> auto power(M const& elem) -> decltype(std::norm(elem)) { return std::norm(elem); } template<class M, class = std::enable_if_t<(M::rank::value >= 1)>> auto power(M const& array) { return accumulate(begin(array), end(array), 0.0, [](auto const& alpha, auto const& omega) { return alpha + power(omega); }); } 这是一个递归(跨维度或等级)“幂”函数,通过计算较低维度子元素的幂,最终给出元素的平方和。 现代 C++ 鼓励使用 if constexpr 以避免使用 SFINAE,如下所示。 template<class M> auto power(M const& array) { if constexpr(M::rank::value >= 1) { return accumulate(begin(array), end(array), 0.0, [](auto const& alpha, auto const& omega) { return alpha + power(omega); }); } else { return std::norm(array); } } 问题在于,if constexpr中的表达式似乎首先必须是有效的表达式。 元素没有名为 rank 的成员类型,因此会出现编译错误。 如果表达式无效,是否有技巧可以使 if constexpr 谓词? if constexpr (requires{requires std::bool_constant</*condition*/>::value;}) 还有一个不太详细的选项: if constexpr (requires{requires /*condition*/;}) 但是后者更糟糕,因为如果编译时不知道条件,它会导致硬错误,而前者只是返回 false。
我正在尝试习惯一些 tmp 概念。 这是一种检查 2 种类型是否可分配的解决方案: 这是最重要的部分: 模板 班级
有没有办法检查函数(特定签名)是否存在,无论它是否是模板化的? 例如: 模板 A级 { 民众: 模板 &l...
这个简单的 has-member SFINAE 技术符合吗?
我正在使用一种简单的(不是特别新的)技术来检查特定名称和类型的类成员是否存在。 以下代码在 Clang 中编译良好,但 MSVC 报告
有没有办法检查函数是否存在,无论它是否是模板化的? 例如: 模板 A级 { 民众: 模板 ...
我想实现一个流式日志库。 我创建了一个 Log_t 类来缓冲日志条目,并对其进行实际输出 毁掉了,像这样: 类 Log_t: 公共 std::ostringstream { 是...
SFINAE 工作正常,但概念约束在类模板实例化中进行了模糊的推论
我正在编写一个曲线类,它可以采用算术类型或算术数组类型作为模板参数。 对于算术数组曲线,本身需要一个包含算术c的数组成员...
模板函数 func 设计为可在任何地方使用。它对任何 T 都有相同的函数体。我只想写一次它的函数体。但功能取决于定义类型 模板功能func<T>设计用于任何地方。对于任何T,它都有相同的函数体。 我只想写一次它的主体。但该功能取决于 type<T> 的定义才能正常工作,并且在某些情况下没有 type<T> 的定义。请参阅以下示例(C++17 中): /// type.h #include <stddef.h> #include <stdint.h> #include <type_traits> template<typename T, typename = void> struct type; template<typename T> size_t func() { return type<T>::magic; } template<typename T> struct type<T, std::enable_if_t<std::is_arithmetic_v<T>>> { static constexpr size_t magic = sizeof(T) * 2; }; /// my_type.h struct MyStruct { int a; static void Dummy(); }; /// my_type.cpp #include "my_type.h" #include "type.h" template<> struct type<MyStruct> { static constexpr size_t magic = 123; }; void MyStruct::Dummy() { (void)func<MyStruct>(); } /// main.cpp #include "my_type.h" #include "type.h" int main(int argc, char **argv) { func<int>(); // OK func<MyStruct>(); // Error } 我怎样才能做到这一点: 只写一次func<T>的正文。 当 func<T> 不完整时,可以调用 type<T>。 注意:有一个 Dummy 函数,用于强制编译器为 func<MyStruct> 生成代码,以便链接器满意。 使用显式实例化: /// my_type.h struct MyStruct { int a; }; // Explicit instantiation declaration extern template size_t func<MyStruct>(); /// my_type.cpp #include "my_type.h" #include "type.h" template<> struct type<MyStruct> { static constexpr size_t magic = 123; }; // Explicit instantiation definition template size_t func<MyStruct>(); 声明它存在于头文件中(因此包含头文件的任何内容都可以看到声明,而不是尝试实例化模板本身),并在类型完成后在源文件中定义它。 您也不再需要Dummy,无论如何也不能保证它能工作。
在C++11中使用SFINAE在具有相同签名的两个函数之间进行选择
我尝试使用 c++11 中的 SFINAE 在具有相同签名但不同主体的两个函数之间进行选择,基于给定 T 类型内应该有或没有 typedef 的事实。对于前...
最小工作示例: #包括 #包括 模板 struct is_array : std::false_type {}; 模板 结构 is_arr...
最小实现: #包括 #包括 模板 自动universal_ref(T&& arr) { for (自动 && v : arr) std::cout <&...
有些事情对我来说不太顺利。这是声明只接受浮点模板参数的类的方法吗? 模板 有些事情对我来说不太顺利。这是声明一个只接受浮点模板参数的类的方法吗? template <typename T, swift::enable_if<std::is_floating_point<T>::value> = nullptr> class my_float; 我无法在此类之外定义方法。无法编译,不知道为什么 您还可以使用static_assert毒害无效类型。 template <typename T> class my_float { static_assert(std::is_floating_point<T>::value, "T is not a floating point type"); // . . . }; 我认为这更直接一些。 使用其他任何一种方法,例如 template <typename T, bool = std::is_floating_point<T>::value> class my_float; template <typename T> class my_float<T, true> { /* . . . */ }; my_float<int,true> 是一个有效的表达式。我并不是说这是一个不好的方法,但如果你想避免这种情况,你必须封装 my_float<typename,bool> 在另一个模板中,以避免暴露 bool 模板参数。 嗯...不完全是SFINAE...但也许,使用模板专业化?如下? template <typename T, bool = std::is_floating_point<T>::value> class my_float; template <typename T> class my_float<T, true> { // ... }; 如果你真的想使用SFINAE,你可以写 template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type> class my_float { // ... }; 或者也(观察示例中没有的指针) template <typename T, typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr> class my_float // ------------------------------------------------^ { }; --编辑-- 按照 Yakk 的建议(谢谢!),您可以混合 SFINAE 和模板专业化,为不同类型的群体开发不同版本的类。 例如以下my_class template <typename T, typename = void> class my_class; template <typename T> class my_class<T, typename std::enable_if<std::is_floating_point<T>::value>::type> { // ... }; template <typename T> class my_class<T, typename std::enable_if<std::is_integral<T>::value>::type> { // ... }; 开发有两个版本(两个不同的部分特化),第一个版本用于浮点类型,第二个版本用于整数类型。并且可以轻松扩展。 确实,这样的东西对我有用(感谢SU3的回答)。 template<typename T, bool B = false> struct enable_if {}; template<typename T> struct enable_if<T, true> { static const bool value = true; }; template<typename T, bool b = enable_if<T,is_allowed<T>::value>::value > class Timer{ void start(); }; template<typename T, bool b> void Timer<T,b>::start() { \* *** \*} 我发布这个答案是因为我不想使用部分专业化,而只想定义外部类的行为。 一个完整的可行示例: typedef std::integral_constant<bool, true> true_type; typedef std::integral_constant<bool, false> false_type; struct Time_unit { }; struct time_unit_seconds : public Time_unit { using type = std::chrono::seconds; }; struct time_unit_micro : public Time_unit { using type = std::chrono::microseconds; }; template<typename T, bool B = false> struct enable_if { }; template<typename T> struct enable_if<T, true> { const static bool value = true; }; template<typename T, bool b = enable_if<T, std::is_base_of<Time_unit, T>::value >::value> struct Timer { int start(); }; template<typename T, bool b> int Timer<T, b>::start() { return 1; } int main() { Timer<time_unit_seconds> t; Timer<time_unit_micro> t2; // Timer<double> t3; does not work ! return 0; }
最小工作示例: #包括 #包括 模板 struct is_array : std::false_type {}; 模板 结构 is_arr...
最小实现: #包括 #包括 模板 自动universal_ref(T&& arr) { for (自动 && v : arr) std::cout <&...