考虑这个完全有效的代码:
#include <type_traits>
template <typename T, typename IndexPack> struct Make;
template <typename T, template <T...> class P, T... Indices>
struct Make<T, P<Indices...>> {
using type = P<(Indices+1)..., (-3*Indices)..., (Indices-1)...>;
};
template <int...> class Pack;
int main() {
static_assert (std::is_same<Make<int, Pack<1,2,3,4>>::type,
Pack<2,3,4,5, -3,-6,-9,-12, 0,1,2,3>>::value, "false");
}
我真正想要的输出是
Pack<2,-3,0, 3,-6,1, 4,-9,2, 5,-12,3>
而不是Pack<2,3,4,5, -3,-6,-9,-12, 0,1,2,3>
。我第一次尝试了
using type = P<(Indices+1, -3*Indices, Indices-1)...>;
但编译器简单地将其理解为无用的逗号运算符。得到我想要的东西的理想语法是什么?如果没有这样的语法,那么最简洁的方法是什么,请记住,使用Indices
3次只是一个例子(我们可能想要使用它超过3次)。请不要告诉我,我必须写一个助手来提取单个包,然后“交织”所有元素。这种噩梦般的方法不是最好的解决方案(只有当我们确切地知道要提取多少个包时,这样的解决方案才有效。)
将定义
template <typename T, template <T...> class P, T I>
struct Component {
using type = P<I+1, -3*I, I-1>;
};
以某种方式提供帮助?对此进行扩展包装?
答案 0 :(得分:4)
是的,你可以递归地结束:
public class BinarySearchTree {
private boolean empty = true;
private int size = 0;
private Node root;
public BinarySearchTree(Node root)
{
this.root = root;
}
public Node[] search(int value)
{
Node parent = null;
Node currentNode = root;
Node[] returnList = new Node[2];
while ( currentNode != null )
{
if (currentNode.getValue() == value)
{
returnList[0] = parent;
returnList[1] = currentNode;
return returnList;
}
else if (value < currentNode.getValue())
{
parent = currentNode;
currentNode = currentNode.getLeft();
}
else if (value > currentNode.getValue())
{
parent = currentNode;
currentNode = currentNode.getRight();
}
}
return returnList;
}
public void add(int value)
{
Node comparingNode = root;
while (true)
{
if (comparingNode.getValue() == value)
{
System.out.println("Tried to add duplicate value of " + value);
break;
}
if (comparingNode.getLeft() == null && comparingNode.getRight() == null)
{
if (value > comparingNode.getValue())
{
comparingNode.setRight(new Node(value));
}
if (value < comparingNode.getValue())
{
comparingNode.setLeft(new Node(value));
}
break;
}
else
{
if (value < comparingNode.getValue())
{
if (comparingNode.getLeft() == null)
{
comparingNode.setLeft(new Node(value));
break;
}
else
{
comparingNode = comparingNode.getLeft();
}
}
if (value > comparingNode.getValue())
{
if (comparingNode.getRight() == null)
{
comparingNode.setRight(new Node(value));
break;
}
else
{
comparingNode = comparingNode.getRight();
}
}
}
}
}
public void remove(int value)
{
Node[] nodesFound = search( value );
Node parent = nodesFound[0];
Node child = nodesFound[1];
boolean fLeft = ( parent.getLeft() == child );
// child node has no children.
if (fLeft)
{
parent.setLeft(null);
}
else
{
parent.setRight(null);
}
if( child.getLeft() != null && child.getRight() == null )
{
// child node has only left child.
if( fLeft )
{
parent.setLeft(child.getLeft());
}
else
{
parent.setRight(child.getLeft());
}
}
else if ( child.getRight() != null && child.getLeft() == null )
{
// child node has only right child.
if( fLeft )
{
parent.setLeft(child.getRight());
}
else
{
parent.setRight(child.getRight());
}
}
else
{
// child node has both children.
if( child.getRight().getLeft() == null )
{
child.getRight().setLeft( child.getLeft() );
parent.setRight( child.getRight() );
}
else
{
Node[] returnList = findLeftMost2Children(child.getRight());
Node leftMostParent = returnList[0];
Node leftMostChild = returnList[1];
leftMostParent.setLeft(null);
leftMostChild.setLeft(child.getLeft());
leftMostChild.setRight(child.getRight());
parent.setRight(leftMostChild);
}
}
}
public Node getRoot()
{
return root;
}
public void outputTreeInOrder( Node root )
{
if( root == null )
return;
// Output the left tree.
if( root.getLeft() != null )
outputTreeInOrder( root.getLeft() );
// Output the current node.
System.out.print( root.getValue() + " " );
// Output the right tree.
if( root.getRight() != null )
outputTreeInOrder( root.getRight() );
}
private Node[] findLeftMost2Children( Node root )
{
Node parent = null;
Node current = root;
while (current.getLeft() != null)
{
parent = current;
current = current.getLeft();
}
Node[] returnList = new Node[2];
returnList[0] = parent;
returnList[1] = current;
return returnList;
}
}
答案 1 :(得分:0)
这是Columbo的解决方案的灵感来源。它使用我最初寻求的包扩展语法,即
using type = typename Merge<T, typename Component<T, P, Indices>::type...>::type;
因此,现在Make
可重复使用,首先使用Triple
,然后使用Quadruple
,因此Indices
的任意数量的用法都可以同时展开。此处Component
是传递到Make
的模板模板模板参数:
#include <type_traits>
template <typename T, typename... Packs> struct Merge;
template <typename T, template <T...> class P1, template <T...> class P2, T... Is, T... Js>
struct Merge<T, P1<Is...>, P2<Js...>> {
using type = P1<Is..., Js...>;
};
template <typename T, typename Pack1, typename Pack2, typename... Packs>
struct Merge<T, Pack1, Pack2, Packs...> {
using type = typename Merge<T, Pack1, typename Merge<T, Pack2, Packs...>::type>::type;
};
template <typename T, template <T...> class P, T I>
struct Triple {
using type = P<I+1, -3*I, I-1>;
};
template <typename T, template <T...> class P, T I>
struct Quadruple {
using type = P<I+1, -3*I, I-1, I>;
};
template <typename T, typename IndexPack,
template <typename U, template <U...> class P, U I> class Component> struct Make;
template <typename T, template <T...> class Z, T... Indices,
template <typename U, template <U...> class P, U I> class Component>
struct Make<T, Z<Indices...>, Component> {
using type = typename Merge<T, typename Component<T, Z, Indices>::type...>::type;
};
template <int...> class Pack;
int main() {
static_assert (std::is_same<Make<int, Pack<1,2,3,4>, Triple>::type,
Pack<2,-3,0, 3,-6,1, 4,-9,2, 5,-12,3>>::value, "false");
static_assert (std::is_same<Make<int, Pack<1,2,3,4>, Quadruple>::type,
Pack<2,-3,0,1, 3,-6,1,2, 4,-9,2,3, 5,-12,3,4>>::value, "false");
}