SFINAE 类型推导给我不完整的类型错误

问题描述 投票:0回答:1

我正在尝试 SFINAE,并尝试获取有关“类函数”对象(函数、函数指针、lambda 以及任何重载括号运算符的内容)的信息,作为练习。我已将代码精简为以下内容:

#include <iostream>
#include <functional>
#include <string>
#include <type_traits>

template<typename Callable, typename = void>
struct function_type_info;

template<typename R, typename G, typename... T>
struct function_type_info<R(G::*)(T...)> {
    using return_type = R;
};

template<typename C>
struct function_type_info<C, typename std::enable_if<!std::is_member_function_pointer<C>::value, C>::type> {
    using return_type = typename function_type_info<decltype(&C::operator())>::return_type;
};

struct Callback {
    int operator()(double, std::string) {
        return 0;
    }
};

int main(int argc, char** argv) {
    auto b = [](double, std::string) -> int { return 0; };
    auto c = Callback{};

    std::cout << std::boolalpha;

    std::cout << std::is_same<function_type_info<decltype(&Callback::operator())>::return_type, int>::value << std::endl;
    std::cout << std::is_same<function_type_info<decltype(b)>::return_type, int>::value << std::endl;
    std::cout << std::is_same<function_type_info<decltype(c)>::return_type, int>::value << std::endl;

    return 0;
}

编译器给我以下错误:

<source>:32:64: error: incomplete type 'function_type_info<main(int, char**)::<lambda(double, std::string)> >' used in nested name specifier
   32 |     std::cout << std::is_same<function_type_info<decltype(b)>::return_type, int>::value << std::endl;
      |                                                                ^~~~~~~~~~~
<source>:32:80: error: template argument 1 is invalid
   32 |     std::cout << std::is_same<function_type_info<decltype(b)>::return_type, int>::value << std::endl;
      |                                                                                ^
<source>:33:64: error: incomplete type 'function_type_info<Callback>' used in nested name specifier
   33 |     std::cout << std::is_same<function_type_info<decltype(c)>::return_type, int>::value << std::endl;
      |                                                                ^~~~~~~~~~~
<source>:33:80: error: template argument 1 is invalid
   33 |     std::cout << std::is_same<function_type_info<decltype(c)>::return_type, int>::value << std::endl;

我不明白为什么会出现此错误。对于 lambda 和 Callback 对象,应接受

function_type_info
的第二个特化:
std::is_member_function_pointer<C>::value
为 false,因此
!std::is_member_function_pointer<C>::value
为 true,因此
std::enable_if<!std::is_member_function_pointer<C>::value, C>::type
应计算为
C
并且模板推导应成功。

如果我将

std::is_member_function_pointer<C>::value, C>::type
更改为
std::is_member_function_pointer<C>::value, void>::type
那么适用于
Callback
,但不适用于 lambda。再次,我不明白为什么这个改变首先使它适用于
Callback
,以及为什么如果它适用于
Callbacks
,它不适用于 lambda。 lambda 的错误如下:

<source>: In instantiation of 'struct function_type_info<main(int, char**)::<lambda(double, std::string)> >':
<source>:32:62:   required from here
<source>:16:11: error: invalid use of incomplete type 'struct function_type_info<int (main(int, char**)::<lambda(double, std::string)>::*)(double, std::__cxx11::basic_string<char>) const, void>'
   16 |     using return_type = typename function_type_info<decltype(&C::operator())>::return_type;
      |           ^~~~~~~~~~~
<source>:7:8: note: declaration of 'struct function_type_info<int (main(int, char**)::<lambda(double, std::string)>::*)(double, std::__cxx11::basic_string<char>) const, void>'
    7 | struct function_type_info;
      |        ^~~~~~~~~~~~~~~~~~
<source>: In function 'int main(int, char**)':
<source>:32:80: error: template argument 1 is invalid
   32 |     std::cout << std::is_same<function_type_info<decltype(b)>::return_type, int>::value << std::endl;

就好像我不被允许引用 lambda 的括号运算符...

注意:我知道我可以通过其他方式获取返回类型信息(

std::result_of
/
std::invoke_result
),但正如我所说,我这样做是为了练习。

c++ templates lambda sfinae
1个回答
0
投票

主要模板使用

template<typename Callable, typename = void>
struct function_type_info;

专业定义为:

template<typename C>
struct function_type_info<C, typename std::enable_if<!std::is_member_function_pointer<C>::value, C>::type> {
    using return_type = typename function_type_info<decltype(&C::operator())>::return_type;
};

错误在于提供

C
作为
std::enable_if
的第二个模板参数。 您只使用
function_type_info
的特化,其中第二个参数是
void
,而不是
C

© www.soinside.com 2019 - 2024. All rights reserved.