根据模板参数不一致执行不同的功能

时间:2015-05-25 14:21:00

标签: c++ templates c++11 sfinae

这绝对是一个微不足道的问题,但我无法弄清楚如何做到这一点。

我有一个模板功能,比如select TOTAL_DELIVERY.CUSTOMER_NAME, TOTAL_DELIVERY.CONTAINER_TYPE, coalesce(TOTAL_DELIVERY.TOTAL_QUANTITY, 0) as TOTAL_DELIVERY, coalesce(TOTAL_PULLOUT.TOTAL_QUANTITY, 0) as TOTAL_PULLOUT, coalesce((TOTAL_DELIVERY.TOTAL_QUANTITY - TOTAL_PULLOUT.TOTAL_QUANTITY), 0) as CUSTOMER_BALANCE from TOTAL_DELIVERY left join TOTAL_PULLOUT on TOTAL_DELIVERY.CUSTOMER_NAME = TOTAL_PULLOUT.CUSTOMER_NAME and TOTAL_DELIVERY.CONTAINER_TYPE = TOTAL_PULLOUT.CONTAINER_TYPE Deliveries Table (View) ================ ---------------------------------------------- CUSTOMER_NAME| CONTAINER_TYPE | TOTAL_QUANTITY -------------+----------------+--------------- Bryan | Slim | 5 -------------+----------------+--------------- Bryan | Jug | 5 -------------+----------------+--------------- Returns Table (View) ============= CUSTOMER_NAME| CONTAINER_TYPE| TOTAL_QUANTITY -------------+---------------+--------------- Bryan | Slim | 5 -------------+---------------+--------------- Expected output =============== Customer | Container | Total_Delivery | Total_Return | Customer_Balance | ---------+-----------+----------------+--------------+------------------ Bryan | Slim | 5 | 5 | 0 | ---------+-----------+----------------+--------------+------------------ Bryan | Jug | 5 | 0 | 5 | ---------+-----------+----------------+--------------------------------- My INCORRECT Result output (incorrect result at the bottom right cell) ========= Customer | Container | Total_Delivery | Total_Return | Customer_Balance | ---------+-----------+----------------+--------------+------------------ Bryan | Slim | 5 | 5 | 0 | ---------+-----------+----------------+--------------+------------------ Bryan | Jug | 5 | 0 | 0 | ---------+-----------+----------------+--------------------------------- 。现在,template <unsigned int N> void my_function()有两个不同的实现,如果my_function大于100,则应使用第一个,如果N小于此值,则应使用另一个。

我试着像这样使用SFINAE:

N

但那是两次声明相同的功能。然后我尝试做类似

的事情
template <unsigned int N, typename = enable_if <N >= 100> :: type> my_function()
{
   // First implementation
}

template <unsigned int N, typename = enable_if <N < 100> :: type> my_function()
{
   // Second implementation
}

然后使用两个不同的布尔值实现这两个函数。没有成功,因为它是部分专业化。

然后我尝试将template <unsigned int N, bool = (N >= 100)> my_function(); 包装为struct参数,并在函数调用中包含bool,但它在专门化类之前专门化了一个成员函数,这是无法完成的。

有合理的方法吗?

3 个答案:

答案 0 :(得分:12)

请改为尝试:

#include <type_traits>
#include <iostream>

template <unsigned int N, typename std::enable_if <N >= 100> :: type* = nullptr> 
void my_function()
{
    std::cout << "N >= 100" << std::endl;
}

template <unsigned int N, typename std::enable_if <N < 100> :: type* = nullptr> 
void my_function()
{
   std::cout << "N < 100" << std::endl;
}

int main()
{
    my_function<42>();
    my_function<100>();
}

Template default parameters do not participate in the overload(因此SFINAE不适用)。另一方面,在上面的代码片段中,依赖模板非类型参数位于赋值的左侧,因此SFINAE启动。

答案 1 :(得分:5)

如果由于某种原因你不喜欢enable_if,你总是可以去标签发送:

String myShapes="circle,square,circle,rectangle"  // This is from a property file
for ( shapeType : myShapes.split("," ) {
   ShapeFactory shapeFactory = new ShapeFactory();
   Shape shape1 = shapeFactory.getShape(shapeType ); 
   shape1.doSomething(); 
}

在这种情况下,我们可以将标签限制为像true_type和false_type这样的简单事物,但通常这可能是另一种方法。

答案 2 :(得分:2)

您可以在退货类型上使用SFINAE:

template <unsigned int N>
enable_if_t<(N >= 100)> my_function()
{
   // First implementation
}

template <unsigned int N>
enable_if_t<(N < 100)> my_function()
{
   // Second implementation
}

目前,您template <unsigned int N, typename T>只有T具有不同的默认类型。

对于部分专业化,您可以转发到结构:

template <unsigned int N, bool = (N >= 100)>
struct my_function_impl;

template <unsigned int N>
struct my_function_impl<N, true>
{
    void operator () const { /* First implementation */}
};

template <unsigned int N>
struct my_function_impl<N, false>
{
    void operator () const { /* Second implementation */}
};

template <unsigned int N>
void my_function() { my_function_impl<N>{}(); }