SFINAE在void和non-void方法之间发送

air*_*ris 2 c++ templates sfinae c++14

我有以下内容:

template <typename T>
struct Base {
    auto func() {
        // do stuff
        auto x = static_cast<T&>(*this).func_impl();
        // do stuff
        return x;
    }
};

struct A : Base<A> {
    int func_impl() {
        return 0;
    }
};

struct B : Base<B> {
    void func_impl() {
    }
};

int main() {
    A a;
    int i = a.func();
    B b;
    b.func();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

问题是我无法func_impl在派生类中声明返回类型,void如图所示B.我尝试使用SFINAE解决问题,如下所示:

template <typename T>
struct Base {
    template <typename = enable_if_t<!is_void<decltype(declval<T>().func_impl())>::value>>
    auto func() {
        // do stuff
        auto x = static_cast<T&>(*this).func_impl();
        // do stuff
        return x;
    }

    template <typename = enable_if_t<is_void<decltype(declval<T>().func_impl())>::value>>
    void func() {
        // do stuff
        static_cast<T&>(*this).func_impl();
        // do stuff
    }
};
Run Code Online (Sandbox Code Playgroud)

但是编译器给出了错误:invalid use of incomplete type 'struct A'invalid use of incomplete type 'struct B'.有没有办法实现我想要的?

max*_*x66 5

试试吧

template <typename T>
struct Base {
    template <typename U = T, typename = enable_if_t<!is_void<decltype(declval<U>().func_impl())>::value>>
    auto func() {
        // do stuff
        return static_cast<T&>(*this).func_impl();
    }

    template <typename U = T, typename = enable_if_t<is_void<decltype(declval<U>().func_impl())>::value>>
    void func() {
        // do stuff
        static_cast<T&>(*this).func_impl();
    }
};
Run Code Online (Sandbox Code Playgroud)

我的意思是...... SFINAE应用于模板; 如果你想在类中启用/禁用方法,它们必须是模板方法(类/结构是模板类/结构不计算的事实:是必须是模板的方法.

SFINAE部分(std::enable_if_t在这种情况下)必须依赖于方法的模板(U在我的例子中).

Ps:无论如何,我没有看到回归的问题 void