我使用GCC 4.9.2得到了"内部编译器错误":
#include <type_traits>
template <typename T, typename, int, template <typename U, U, U> class>
struct Sort;
template <typename T, template <T...> class Z, T N, T... Is,
template <typename U, U, U> class Comparator>
struct Sort<T, Z<N, Is...>, 0, Comparator> {
template <T I>
struct less_than : std::integral_constant<bool, Comparator<T, I, N>::value> {
};
};
int main() {}
Run Code Online (Sandbox Code Playgroud)
错误消息指出:
c:\ ADandD> g ++ -std = c ++ 14 ComparatorAndSorterTGeneralized.cpp ComparatorAndSorterTGeneralized.cpp:254:80:内部编译器错误:在tsubst中,在cp/pt.c:11738
Run Code Online (Sandbox Code Playgroud)template<T I> struct less_than : std::integral_constant<bool, Comparator<T,I,N>::value> {}; ^如果合适,请提交完整的错误报告,并提供预处理的来源.有关说明,请参阅 …
To make a preorder traversal of a nested pack of types (i.e. a tree of types), and then carry out an action at each leaf, I've worked out an algorithm already (and tested to work correctly):
template <typename T>
struct HasChildren : std::false_type {};
template <template <typename...> class P, typename... Types>
struct HasChildren<P<Types...>> : std::true_type {};
template <typename, typename> struct Merge;
template <template <typename...> class P1, template <typename...> class P2, typename... Ts, typename... Us>
struct Merge<P1<Ts...>, P2<Us...>> {
using type …Run Code Online (Sandbox Code Playgroud) 有人可以推荐一种更优雅的方式来实现这些编译时常量吗?
template <int> struct Map;
template <> struct Map<0> {static const int value = 4;};
template <> struct Map<1> {static const int value = 8;};
template <> struct Map<2> {static const int value = 15;};
template <int> struct MapInverse;
template <> struct MapInverse<4> {static const int value = 0;};
template <> struct MapInverse<8> {static const int value = 1;};
template <> struct MapInverse<15> {static const int value = 2;};
Run Code Online (Sandbox Code Playgroud)
这个值需要在我的程序中是constexpr,但逆映射值更新很繁琐(容易出错或忘记做).
考虑这个输出:
int foo (int, char) {std::cout << "foo\n"; return 0;}
double bar (bool, double, long ) {std::cout << "bar\n"; return 3.5;}
bool baz (char, short, float) {std::cout << "baz\n"; return true;}
int main() {
const auto tuple = std::make_tuple(5, 'a', true, 3.5, 1000, 't', 2, 5.8);
multiFunction<2,3,3> (tuple, foo, bar, baz); // foo bar baz
}
Run Code Online (Sandbox Code Playgroud)
因此,multiFunction<2,3,3>获取前2个元素tuple并将它们传递给foo接下来的3个元素tuple并将它们传递给bar等等...我得到了这个工作(除非函数有重载,这是一个单独的问题).但是所调用的每个函数的返回值都会丢失.我希望将这些返回值存储在某处,例如
std::tuple<int, double, bool> result = multiFunction<2,3,3> (tuple, foo, bar, baz);
Run Code Online (Sandbox Code Playgroud)
但我不知道如何实现这一点.对于那些想要帮助完成这项工作的人来说,这是我目前为止的(更新的)工作代码,它仅将输出存储到字符串流中.不容易获得所有值,特别是如果流中保存的对象是复杂类.
#include <iostream> …Run Code Online (Sandbox Code Playgroud) 给定任意数量的包装,从每个包装中取出第一种类型,将它们放在一起.然后是每个包中的第二种类型,将它们放在一起等等......然后将它们全部合并.任何左撇子都会在他们之间重复这个过程.例如,使用整数表示不同类型以获得更好的可读性,
InterlacePacks<Pack<1 2 3 4>, Pack<5 6 7>, Pack<8 9 10 11 12>>::type
Run Code Online (Sandbox Code Playgroud)
会给
Pack<1 5 8 2 6 9 3 7 10 4 11 12>
Run Code Online (Sandbox Code Playgroud)
如果所有包只是相同的大小,则以下代码有效.我现在完全陷入对付"左结转"的时候,包是不同的尺寸.到目前为止,这是我的代码.我解释每个阶段,以便你知道我的计划是什么:
#include <iostream>
// First a helper to remove the first N types from a pack:
template <int, typename> struct RemoveHead;
template <typename Pack>
struct RemoveHead<0, Pack> { using type = Pack; };
template <template <typename...> class P, typename First, typename... Rest>
struct RemoveHead<0, P<First, Rest...>> { using type = …Run Code Online (Sandbox Code Playgroud) 功能
template <typename Container, typename Comparator, typename Predicate>
void sortButKeepSomeFixed (Container& c, const Comparator& comp, const Predicate& pred)
Run Code Online (Sandbox Code Playgroud)
是c按照排序标准对容器进行排序comp,但满足的那些元素pred在排序后应保持固定在原始位置(即不受排序影响).
我试图适应快速排序以适应这一点,但无法想到它.最后,我决定调整原油选择排序来完成工作:
#include <iostream>
#include <vector>
std::vector<int> numbers = {5,7,1,8,9,3,20,2,11};
template <typename Container, typename Comparator, typename Predicate>
void sortButKeepSomeFixed (Container& c, const Comparator& comp, const Predicate& pred) { // O(n^2), but want O(nlogn) on average (like quick sort or merge sort)
const std::size_t N = c.size();
std::size_t i, j, minIndex;
for (i = 0; i < …Run Code Online (Sandbox Code Playgroud) 我们来看看是否
struct Thing {
int foo(double, bool) {return 0;}
};
Run Code Online (Sandbox Code Playgroud)
int foo(double, bool)在编译期间有成员函数.有很多方法可以做到这一点,而且大多数只是其他方式的变体.有人会想到一种与我在这里提到的5种方式截然不同(或至少相当有创意)的方式吗?我只是想学习一些模板和SFINAE的新技术.
#include <iostream>
#include <type_traits>
// Using void_t (this includes using std::is_detected).
template <typename T>
using void_t = void;
template <typename T, typename = void>
struct has_foo : std::false_type {};
template <typename T>
struct has_foo<T,
void_t<decltype(static_cast<int>(std::declval<T>().foo(double{}, bool{})))>
> : std::true_type {};
// Using the ... default argument.
template <typename T>
struct hasfoo {
template <typename U>
static std::true_type test (decltype(static_cast<int(T::*)(double, bool)>(&T::foo))*); // or 'decltype(static_cast<int>(std::declval<U>().foo(double{}, bool{})))*' works fine …Run Code Online (Sandbox Code Playgroud) 参考下面的代码,有人可以弄清楚如何适应
template <typename RET, typename... ARGS1, typename... ARGS2>
RET Mediator::change (Object* o, RET (Object::*f)(ARGS1...), ARGS2&&... args) {
const std::tuple<ARGS2...> t(args...);
for (Object* x : objects)
(x->*f)(std::get<0>(t), o->rating, std::get<1>(t), o->str);
}
Run Code Online (Sandbox Code Playgroud)
因此,每次更改ARGS2时,我都不必重写不同版本.我不介意在参数只包含4个参数的情况下这样做,但是你可以想象如果它远大于4则需要泛化.ARGS1中的类型......应该由不同的类型组成,所以应该有一种方法获得std :: get <0>(t),std :: get <1>(t),...正确放置,以便不需要像上面那样手动完成(即使有是重复类型,然后它们可以简单地放在重复类型的第一个插槽中).下面是完整的代码(上下文是,当Mediator的每个Object订阅者更改时,Mediator的其他Object订阅者应相应地更改):
#include <iostream>
#include <string>
#include <vector>
#include <tuple>
struct Mediator {
std::vector<struct Object*> objects;
void registerObject (Object* o) {objects.emplace_back(o);}
template <typename RET, typename... ARGS1, typename... ARGS2>
RET change (Object*, RET (Object::*)(ARGS1...), ARGS2&&...);
};
struct Object {
int value;
double rating;
char letter;
std::string …Run Code Online (Sandbox Code Playgroud) PowerSet<Pack<Types...>>::type是给出一个由所有子集形成的包组成的包Types...(现在假设静态断言,每个类型Types...都是不同的).例如,
PowerSet<Pack<int, char, double>>::type
Run Code Online (Sandbox Code Playgroud)
是的
Pack<Pack<>, Pack<int>, Pack<char>, Pack<double>, Pack<int, char>, Pack<int, double>, Pack<char, double>, Pack<int, char, double>>
Run Code Online (Sandbox Code Playgroud)
现在,我已经解决了这个练习并对其进行了测试,但我的解决方案很长,并希望听到一些更优雅的想法.我不是要求任何人审查我的解决方案,而是建议一个新的方法,或许用一些伪代码描绘他们的想法.
如果您想知道,这就是我所做的:首先,我从高中回忆起一组N个元素有2 ^ N个子集.每个子集对应于N位二进制数,例如001010 ... 01(N位长),其中0表示该元素在子集中,1表示该元素不在子集中.因此000 ... 0表示空子集,111 ... 1表示整个集合本身.因此,使用(模板)序列0,1,2,3,... 2 ^ N-1,我形成了2 ^ N个index_sequence,每个都对应于该序列中整数的二进制表示,例如index_sequence <1,1 ,0,1>将对应于该序列中的13.然后将那些2 ^ N index_sequence中的每一个转换为期望的2 ^ N个子集Pack<Types...>.
我的解决方案很长,我知道有一种比上面描述的机械方法更优雅的方法.如果你想到了一个更好的计划(也许更短,因为它更加递归或其他),请发表您的想法,以便我可以采取更好的计划,希望写出更短的解决方案.如果您认为可能需要一些时间(除非您愿意),我不希望您完整地写出您的解决方案.但是目前,我想不出比我做的更好的方式了.这是我目前的长期解决方案,如果你想阅读它:
#include <iostream>
#include <cmath>
#include <typeinfo>
// SubsetFromBinaryDigits<P<Types...>, Is...>::type gives the sub-pack of P<Types...> where 1 takes the type and 0 does not take the type. The size of the two packs …Run Code Online (Sandbox Code Playgroud) 在这段代码中,我试图Test从 usingArg到 using进行概括Args...。问题是默认的模板参数。我在下面编译的内容,除非我取消注释 main() 中的注释行:
#include <iostream>
#include <type_traits>
struct A {
void foo(int) const {}
void foo(int, bool, char) const {}
};
template <typename...> struct voider { using type = void; };
template <typename... Ts>
using void_t = typename voider<Ts...>::type;
template <typename T, typename Arg, typename = void_t<T>>
struct Test : std::false_type {};
template <typename T, typename Arg>
struct Test<T, Arg, void_t<decltype(std::declval<T&>().foo(std::declval<Arg>()))>> :
std::true_type {};
// Trying to generalize Test with Args... instead …Run Code Online (Sandbox Code Playgroud)