Mẫu quá tải C ++ khi gán giá trị hoặc hàm gọi lại


8

Cố gắng làm một cái gì đó như ...

template <class T>
struct Wrapper
{
    template <class U>
    void set(const U& u) { myT = u; }

    template <class F>
    void set(F f) { myT = f(); }

    T myT;
};

Tôi biết tôi cần sử dụng SFINAE ở đây nhưng làm cách nào để phân biệt tham số gọi lại với tham số giá trị? Sẽ an toàn khi cho rằng giá trị không thể được sử dụng làm cuộc gọi lại.

Tôi đã thử enable_ifvới is_function, result_of, invoke_result, is_invocable, và những người khác, nhưng không ai trong số nó hoạt động đúng. Nó thậm chí có thể?

Câu trả lời:


9

Bạn có thể làm điều đó mà không cần SFINAE:

template<class U>
void set(const U& u) { 
    if constexpr (std::is_invocable_v<U>)
        myT = u();
    else
        myT = u;
}

hoặc theo cách chung hơn:

template<class U>
void set(U&& u) { 
    if constexpr (std::is_invocable_v<U>)
        myT = std::forward<U>(u)();
    else
        myT = std::forward<U>(u);
}

2
thích constexprhơn SFINAE vì thời gian biên dịch tốt hơn
Dev Null

7

Có, bạn có thể áp dụng SFINAE với sự trợ giúp của std::is_invocable(kể từ C ++ 17).

template <class U>
std::enable_if_t<!std::is_invocable_v<U>> set(const U& u) { myT = u; }

template <class F>
std::enable_if_t<std::is_invocable_v<F>> set(F f) { myT = f(); }

TRỰC TIẾP


4

Quá tải có chức năng làm đối số có thể được định nghĩa là:

template <typename R>
   void set(R (*f)())
   {
      myT = f();
   }

Mã trình diễn:

#include <iostream>

template <class T>
struct Wrapper
{
   template <class U>
      void set(const U& u)
      {
         std::cout << "In set(const U& u)\n";
         myT = u;
      }

   template <typename R>
      void set(R (*f)())
      {
         std::cout << "In set(R (*f)())\n";
         myT = f();
      }

   T myT;
};

short foo()
{
   return 2u;
}

int main()
{
   Wrapper<int> a;
   a.set(1u);
   a.set(foo);
}

Đầu ra:

In set(const U& u)
In set(R (*f)())

1
Đây là một giải pháp kém. Bạn chỉ chấp nhận con trỏ chức năng. Bạn không thể vượt qua lambdas hay "các lớp có thể gọi được".
Bktero
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.