【问题标题】:In a template, if a dependent name is a function, call it在模板中,如果依赖名称是函数,则调用它
【发布时间】:2018-11-22 04:07:12
【问题描述】:

在我的 TClass<T>::foo() 函数中,当且仅当 T 是函数类型时,我想调用 T 实例。

#include <iostream>
#include <functional>

template<class T>
struct TClass
{
    TClass(T value) : value(value) {}
    T value;
    void foo()
    {
        // if(value is std::function)
        //     call function;
    }
};

int main()
{
    TClass<int> t1{0};
    t1.foo();
    TClass<std::function<void()>> t2{[](){ std::cout << "Hello, World!\n"; }};
    t2.foo();
}

我该怎么做?

【问题讨论】:

  • “函数类型” - 仅限std::function?函数指针?拉姆达斯?函数类型(void(int))?重载operator()的类?
  • 我不知道这个变化@YSC。这是相当可观的。
  • @Barry 你会回答原始状态的问题吗?
  • 不直接相关,但 C++17 有 std::invoke,您可能在这种情况下会觉得有用/有趣。

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


【解决方案1】:

在 C++11 中,最简单的方法是通过辅助函数重新推导值:

template <typename U>
auto foo_helper(U const& f, int) -> decltype(f()) {
    return f();
}

template <typename U>
void foo_helper(U const&, long) {}

void foo() {
    foo_helper(value, 0);
}

0int 的转换比它到long 的转换要好,所以如果第一个重载是可行的 - 它将是首选。如果第一个重载不可行,那么我们调用第二个。


如果你真的只关心std::function,那么我们可以有更简单的重载:

void foo_helper(std::function<void()> const& f) {
    f();
}

template <typename T>
void foo_helper(T const&) { }

void foo() {
    foo_helper(value);
}

【讨论】:

  • 没有enable_if:很好!
  • decltypeenable_if 实际上是同一个东西,@YSC。
  • @SergeyA 请向图书馆作者解释一下。我厌倦了它的冗长。
【解决方案2】:

在 C++17 中你可以这样做:

void foo() {
    if constexpr (std::is_invocable_v<T>) {
        value();
    }
}

如果你只想允许std::function,你需要你自己的特质,例如:

template <class T>
struct is_stdfunction: std::false_type {};

template <class T>
struct is_stdfunction<std::function<T>: std::true_type {};

template <class T>
constexpr bool is_stdfunction_v = is_stdfunction<T>::value;

// Then in foo():
void foo() {
    if constexpr (is_stdfunction_v<std::decay_t<T>>) {
        value();
    }
}

【讨论】:

    【解决方案3】:

    为什么不partial specialization

    考虑:

    #include <iostream>
    #include <functional>
    
    template<class T>
    struct TClass {
        TClass(T value) : value(value) {}
        T value;
        void foo() {
            std::cout << "T - other" << std::endl;
        }
    };
    
    template<class T>
    struct TClass<std::function<T>> {
        TClass(std::function<T>  value) : value(value) {}
        std::function<T> value;
        void foo() {
            std::cout << "std::function" << std::endl;
        }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-13
      • 1970-01-01
      • 1970-01-01
      • 2012-04-09
      • 2021-02-12
      • 1970-01-01
      • 2015-01-26
      相关资源
      最近更新 更多