簡體   English   中英

C ++模板專業化:更改operator()的返回類型?

[英]C++ template specialization: change return type of operator()?

在下面的類中,我定義了一個operator()返回一個return_T的向量:

#include <vector>

template <typename return_T, typename ... arg_T>
class A
{
public:
    std::vector<return_T> operator()(arg_T... args);
};

這是有效的,除了return_T = void的情況,因為vector<void>是不可能的。 所以我需要以某種方式定義A<void, arg_T>::operator() 我正在嘗試以下代碼:

#include <vector>

template <typename return_T, typename ... arg_T>
class A
{
public:
    auto operator()(arg_T... args);
};

template<typename return_T, typename... arg_T>
auto A<return_T, arg_T...>::operator()(arg_T... args) -> typename std::enable_if<!std::is_void<return_T>::value, std::vector<return_T>>::type
{ }

template<typename return_T, typename... arg_T>
auto A<void, arg_T...>::operator()(arg_T... args) -> void
{ }

但編譯器不喜歡它。

error : prototype for 'typename std::enable_if<(! std::is_void<_Tp>::value), std::vector<_Tp> >::type A<return_T, arg_T>::operator()(arg_T ...)' does not match any in class 'A<return_T, arg_T>'
   auto A<return_T, arg_T...>::operator()(arg_T... args) -> typename std::enable_if<!std::is_void<return_T>::value, std::vector<return_T>>::type

error : candidate is: auto A<return_T, arg_T>::operator()(arg_T ...)
       auto operator()(arg_T... args);
            ^

error : invalid use of incomplete type 'class A<void, arg_T ...>'
   auto A<void, arg_T...>::operator()(arg_T... args) -> void
                                                        ^

當然,我可以使用void operator()輕松編寫第二個類,但我很好奇是否可以使用單個類完成。 所以我的問題是:這可能嗎?

您可以創建一個專門的“traits”類,而不是專門化A

template <typename return_T>
struct Traits {
    using ReturnType = std::vector<return_T>;
};

template <>
struct Traits<void> {
    using ReturnType = void;
}

template <typename return_T, typename ... arg_T>
class A
{
public:

    typename Traits<return_T>::ReturnType operator()(arg_T... args);
};

這樣你就不必專門化A ,如果A很大就很方便,而且專業化它比僅僅專門化一個小特征類更復雜。

#include <type_traits>
#include <utility>
#include <vector>

template <typename return_T, typename... arg_T>
class A
{
public:
    auto operator()(arg_T... args)
    {
        return invoke(std::is_void<return_T>{}, std::forward<arg_T>(args)...);
    }

private:
    void invoke(std::true_type, arg_T&&... args)
    {
    }

    std::vector<return_T> invoke(std::false_type, arg_T&&... args)
    {
        return {};
    }
};

測試:

int main()
{
    A<int, char, short> a;    
    static_assert(std::is_same<decltype(a('x', 5)), std::vector<int>>{}, "!");

    A<void, char, short> b;
    static_assert(std::is_same<decltype(b('x', 5)), void>{}, "!");    
}

DEMO

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM