- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
这是 another question 的后续事件.它指的是同一个问题(我希望),但使用了一个完全不同的例子来说明它。原因是在前面的示例中,只有实验性 GCC 4.9 因编译器错误而失败。在此示例中,Clang 和 GCC 4.8.1 也以不同的方式失败:Clang 产生了意外结果,而 GCC 4.8.1 报告了不同的错误消息。
上一个问题的答案或多或少说代码是有效的,问题出在 GCC 的实验版本上。但这个结果让我更加怀疑。几个月来,我一直被我怀疑相关(或相同)的问题所困扰,这是我第一次有一个小的具体例子来说明。
所以,这里有一些代码。首先,一些通用代码将 SFINAE 应用于由可变参数模板别名元函数 F
指定的任意测试:
#include <iostream>
using namespace std;
using _true = integral_constant <bool, true>;
using _false = integral_constant <bool, false>;
template <typename T> using pass = _true;
template <template <typename...> class F>
struct test
{
template <typename... A> static _false _(...);
template <typename... A> static pass <F <A...> > _(int);
};
template <template <typename...> class F, typename... A>
using sfinae = decltype(test <F>::template _<A...>(0));
其次,一个特定的测试,检查给定的类是否定义了一个名为type
的类型:
template <typename T> using type_of = typename T::type;
template <typename T> using has_type = sfinae <type_of, T>;
最后,举个例子:
struct A { using type = double; };
int main()
{
cout << has_type <int>() << ", ";
cout << has_type <A>() << endl;
}
预期结果将是 0, 1
。 Clang 说 0, 0
。 GCC 4.8.1 说
tst.cpp: In substitution of ‘template<class T> using type_of = typename T::type [with T = A ...]’:
tst.cpp:15:51: required from ‘struct test<type_of>’
tst.cpp:19:67: required by substitution of ‘template<template<class ...> class F, class ... A> using sfinae = decltype (test:: _<A ...>(0)) [with F = type_of; A = {T}]’
tst.cpp:24:58: required from here
tst.cpp:23:56: error: ‘A ...’ is not a class, struct, or union type
template <typename T> using type_of = typename T::type;
^
GCC 4.9 说
tst.cpp:19:67: required by substitution of ‘template<template<class ...> class F, class ... A> using sfinae = decltype (test:: _<A ...>(0)) [with F = type_of; A = {T}]’
tst.cpp:24:58: required from here
tst.cpp:15:51: error: pack expansion argument for non-pack parameter ‘T’ of alias template ‘template<class T> using type_of = typename T::type’
template <typename... A> static pass <F <A...> > _(int);
^
(行号可能会有所不同)。所以,一切都以不同的方式失败了。
现在,这里有一个解决方法。元函数 car
从给定的包中选择第一个类型,然后将测试重新定义为 type_of2
,现在是可变参数:
template <typename... T> struct car_t;
template <typename... T> using car = type_of <car_t <T...> >;
template <typename T, typename... Tn>
struct car_t <T, Tn...> { using type = T; };
template <typename... T> using type_of2 = typename car <T...>::type;
template <typename T> using has_type2 = sfinae <type_of2, T>;
int main()
{
cout << has_type2 <int>() << ", ";
cout << has_type2 <A>() << endl;
}
现在所有三个编译器都按预期说 0, 1
。有趣的是,对于任何版本的 GCC,我们都必须删除 has_type
(即使我们不使用它),只留下 has_type2
;否则我们会有类似的错误。
总结:我发现一个模板需要一个可变参数模板参数的问题
template <typename...> class F
我们实际输入表单的非可变模板别名
template <typename T> using alias = // ... anything including T or not
最后调用 F
就好像它是可变参数一样:
F <A...>
到目前为止,意见认为这是有效的,但现在似乎三个编译器不同意。所以问题又来了:有效吗?
对我来说这很重要,因为我有几十个现有代码文件,假设这是有效的,现在我无论如何都需要重新设计(因为这些编译器存在实际问题),但确切的重新设计将取决于回答。
最佳答案
这并不能回答上面的代码是否有效的问题,但这是我在提出问题后不久通过实验发现的一个非常漂亮的解决方法,我认为分享一下很有用。
只需要以下定义:
template <template <typename...> class F>
struct temp { };
template <typename... A, template <typename...> class F>
F <A...> subs_fun(temp <F>);
template <template <typename...> class F, typename... A>
using subs = decltype(subs_fun <A...>(temp <F>()));
那么,无论在哪里F <A...>
会有问题,替换为subs <F, A...>
.而已。我无法解释原因,但到目前为止它在所有情况下都有效。
例如,在问题的 SFINAE 示例中,只需替换行
template <typename... A> static pass <F <A...> > _(int);
通过
template <typename... A> static pass <subs <F, A...> > _(int);
这只是一次更改,所有剩余代码保持不变。您不需要重新定义或包装每个用作 F
的模板元函数.这是 live example .
如果 F <A...>
确实有效并且编译器最终支持它,再次切换回来很容易,因为更改很少。
我觉得这很重要,因为它只允许在两行中指定 SFINAE 测试
template <typename T> using type_of = typename T::type;
template <typename T> using has_type = sfinae <type_of, T>;
并且是完全通用的。通常,每个这样的测试至少需要 10 行代码和 <type_traits>
的实现。充满了这样的代码。在某些情况下,此类代码块被定义为宏。有了这个解决方案,模板就可以完成这项工作,并且不需要宏。
关于c++ - 可变模板别名作为模板参数(第 2 部分),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20291352/
为什么禁用类型像 type t = A of int | B of string * mutable int 虽然允许此类类型: type t = A of int | B of string * i
我正在寻找一种类似结构的数据结构,我可以从中创建多个实例并具有某种类型提示而不是不可变的。 所以我有这样的东西: class ConnectionConfig(NamedTuple): nam
我需要转到引用的结构: class SearchKnot { var isWord : Bool = false var text : String = "" var to
如sec 10.4.3中所述 当控制进入执行时,执行以下步骤 功能对象F(调用者)中包含的功能代码的上下文 提供thisArg,而调用方提供argumentsList: 如
i make a game that start display Activity indicator And activity indicator bottom display UiLable wi
编辑:我在这里不断获得支持。只是为了记录,我认为这不再重要。自从我发布它以来我就不再需要它了。 我想在 Scala 中执行以下操作... def save(srcPath: String, destP
使用可变对象作为 Hashmap 键是一种不好的做法吗?当您尝试使用已修改足以更改其哈希码的键从 HashMap 中检索值时,会发生什么? 例如,给定 class Key { int a; /
如果您在Kotlin中访问List类型的Java值,则将获得(Mutable)List!类型。 例如。: Java代码: public class Example { public stati
我编写了 str 类(内置)的以下扩展,以便执行以下操作:假设我有字符串 "Ciao" ,通过做"Ciao" - "a"我想要的结果是字符串 "Cio" 。这是执行此操作的代码,并且运行良好: cla
使用可变对象作为 Hashmap 键是一种不好的做法吗?当您尝试使用已修改足以更改其哈希码的键从 HashMap 中检索值时,会发生什么? 例如,给定 class Key { int a; /
我正在为我的公司设计一个数据库来管理商业贷款。每笔贷款都可以有担保人,可以是个人或公司,在借款业务失败时作为财务支持。 我有 3 个表:Loan、Person 和 Company,它们存储明显的信息。
我使用二进制序列化从 C# 类中保存 F# 记录。一切正常: F#: type GameState = { LevelStatus : LevelStatus
import javax.swing.JOptionPane; public class HW { public static void main(String[] args) { Strin
使用 flatbuffer mutable 有多少性能损失? 是否“正确”使用 FlatBuffers 来拥有一个应该可编辑的对象/结构(即游戏状态) 在我的示例中,我现在有以下类: class Ga
std::function create_function (args...) { int x = initial_value (args...); return [x] () mut
我需要在 for 循环中找到用户输入的字符。我通常会这样做 如果(句子[i] == 'e') 但是因为在这里,'e' 将是一个单字母字符变量,我不知道如何获取要比较的值。我不能只输入 if (sent
我有一个这样的算法: let seed: Foo = ... let mut stack: Vec = Vec::new(); stack.push(&seed); while let Some(ne
这个问题可能看起来非常基础,但我很难弄清楚如何做。我有一个整数,我需要使用 for 循环来循环整数次。 首先,我尝试了—— fn main() { let number = 10; // An
如果我有以下结构: struct MyStruct { tuple: (i32, i32) }; 以及以下函数: // This will not compile fn function(&mut s
我希望在每个 session 的基础上指定列的默认值。下面的脚本不起作用,但描述了我想如何使用它。我目前使用的是 MySQL 5.5.28,但如果需要可以升级。 CREATE TABLE my_tbl
我是一名优秀的程序员,十分优秀!