2016-02-29 73 views
2

我这一段代码:std :: is_same用于void函数(...)和void类型?

template <class FunctionType> class Entry { 
    std::function<FunctionType> internalFunction; 

    template<class... Arguments> 
    auto operator()(Arguments... arguments) -> decltype(internalFunction(arguments...)){ 

     if (std::is_same<decltype(internalFunction(arguments...)), void>::value) { 
      internalFunction(arguments...); 
     } else { 
      auto result = internalFunction(arguments...); 

      return result;  
     } 
    } 
}; 

Entry类,就是要包装的std::function。它适用于所有返回类型,但有一个例外 - void。我无法让它工作。我也尝试过std::is_void,它不会为​​类型的函数返回true。 std::is_same也一样。

如何解决这个问题?

+0

'internalFunction'返回'std :: function'。我无法弄清楚你想要检查什么。 'internalFunction'永远不会返回'void'。 –

回答

3

它遵循另一种解决方案,即一个基于sfinae而不是部分专业化
我试图提供一个最小的完整示例。
在这个例子中,我还介绍了完美转发,但它与问题中的完全不同,所以我决定让它更类似于那个。

#include<functional> 
#include<type_traits> 


template <class FunctionType> class Entry { 
    std::function<FunctionType> internalFunction; 

    template<typename R, typename... Args> 
    typename std::enable_if<std::is_void<R>::value>::type 
    invoke(Args... args) { 
     internalFunction(args...); 
    } 

    template<typename R, typename... Args> 
    typename std::enable_if<not std::is_void<R>::value, R>::type 
    invoke(Args... args) { 
     return internalFunction(args...); 
    } 

public: 
    Entry(std::function<FunctionType> f) 
     : internalFunction{f} { } 

    template<class... Arguments> 
    auto operator()(Arguments... arguments) -> decltype(internalFunction(arguments...)){ 
     return invoke<typename std::function<FunctionType>::result_type>(arguments...); 
    } 
}; 


int f() { return 42; } 
void g() { } 


int main() { 
    Entry<int()> e1(&f); 
    e1(); 
    Entry<void()> e2(&g); 
    e2(); 
} 

详情约SFINAEhere

+0

这就是我需要的。谢谢:) – Nuurek

+0

不客气。 :-) – skypjack

4
return internalFunction(arguments...); 

这工作即使internalFunction回报void

试图把结果存储在一个中间对象是不行的,因为你不能创建void类型的对象,因为它不是一个对象类型。

您的if不起作用,因为if是运行时条件,编译器仍然需要编译条件的两个分支,因此它们都必须是有效的C++。

如果您需要创建中间结果类型的变量,则不能将该代码用于void的情况。你可以写返回void函数的偏特:

template <class FunctionType> class Entry { 
    std::function<FunctionType> internalFunction; 

    template<class... Arguments> 
    auto operator()(Arguments... arguments) -> decltype(internalFunction(arguments...)) 
    { 

     auto result = internalFunction(arguments...); 

     return result;  
    } 
}; 

template <class... ArgTypes> class Entry<void(ArgTypes...)> { 
    std::function<void(ArgTypes...)> internalFunction; 

    template<class... Arguments> 
    void operator()(Arguments... arguments) { 
     internalFunction(arguments...); 
    } 
}; 

这将不会返回void功能,但不适合返回void函子的工作,这样做是有点困难。

+0

我必须存储结果,它不是整个代码。 – Nuurek

+0

然后,您需要专门化模板,并有两个定义,一个用于'void'返回,另一个用于其他所有。 –

+0

@Nuurek这会让事情变得非常难看 - 区分函数返回void和non void –