Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Can';t使用基类模板成员函数_C++_C++14 - Fatal编程技术网

C++ Can';t使用基类模板成员函数

C++ Can';t使用基类模板成员函数,c++,c++14,C++,C++14,出于某种原因,我可以看到最顶层的模板X::fn(T&&),但不能看到基类版本。使用关键字导入它们不起作用。据我了解: 示例代码: #include <iostream> #include <type_traits> #define ENABLE_IF(...) std::enable_if_t<__VA_ARGS__, int> = 0 struct dummy {}; template<typename T> struct always_

出于某种原因,我可以看到最顶层的
模板X::fn(T&&)
,但不能看到基类版本。使用
关键字导入它们不起作用。据我了解:

示例代码:

#include <iostream>
#include <type_traits>

#define ENABLE_IF(...) std::enable_if_t<__VA_ARGS__, int> = 0

struct dummy {};

template<typename T>
struct always_false : std::false_type {};

template<typename...Ts>
struct X;

template<typename Tx, typename T, typename...Ts>
struct X<Tx, T, Ts...> : X<Tx, Ts...>
{
    using X<Tx, Ts...>::fn;

    template<typename R, ENABLE_IF(std::is_same<T, R>::value)>
    auto fn(R&& x)
    {
        return x;
    }
};

template<typename Tx>
struct X<Tx>
{
    template<typename R>
    auto fn(R&& x)
    {
        static_assert(always_false<R>::value, "Invalid type");
    }
};

int main()
{
    X<dummy, int, float> x;
    std::cout << x.fn(1) << std::endl;
    std::cout << x.fn(1.f) << std::endl;
    std::cout << "Hello, world!\n";
}
#包括
#包括
#如果(…)std::如果t=0,则定义启用
结构虚拟{};
模板
结构总是\u false:std::false\u类型{};
模板
结构X;
模板
结构X:X
{
使用X::fn;
模板
自动fn(R&x)
{
返回x;
}
};
模板
结构X
{
模板
自动fn(R&x)
{
静态断言(始终为false::value,“无效类型”);
}
};
int main()
{
X;
std::cout两件事:

  • 与其他
    fn
    变体一样,您的基线捕获所有版本的
    fn
    也是一个很好的匹配;因此,充其量只能得到一个模糊的重载错误

  • >P>隐藏使用声明不考虑完整的签名(函数模板将包含模板参数列表)。它1)名称(2)(函数)参数类型列表,3)CV资格,和4)REF限定符(如果有的话)。如果四个都匹配,则基类函数模板将被隐藏,并且不会由using声明带入。值得注意的是,模板参数列表不会被考虑。在您的案例中,不同的
    fn
    s之间唯一不同的是模板参数列表;它们都具有相同的名称、相同的参数类型列表和相同的cv限定,和相同的ref限定符(或缺少)。因此,最派生的
    fn
    将隐藏基类中的所有
    fn
    s

    GCC似乎没有实现这一部分到规范,并在决定隐藏时考虑模板参数列表。

    此部分的一个可能修复方法是将
    enable_if
    移动到函数参数,隐藏检查会考虑该参数


    <> C++中的过载解决方法是:

  • 名称查找以构建一组候选函数和函数模板
  • 对于每个候选函数模板,执行模板参数推断。如果推断失败,则将其从重载集中删除。如果推断成功,则用推断的专用化替换候选函数模板
  • 从候选者集中删除不可行的候选者
  • 如果集合为空,则返回错误。否则,在候选函数中找到最佳可行函数
  • 隐藏操作在第一步:如果声明是隐藏的,则不会通过名称查找找到它,因此它不在候选的初始集合中,并且在任何情况下都不会通过重载解析进行考虑,无论在步骤2、3或4中发生了什么。隐藏声明实际上并不存在ad分辨率

    因此,在您的例子中,基类
    fn
    s都是隐藏的。这意味着什么?这意味着通过名称查找找到的唯一候选对象是来自最派生类的
    int
    ,而不是其他。如果模板参数推导和替换成功,则将调用该函数模板。如果失败(如
    x.fn(2.f)中所示)
    case),那么就没有可行的候选人了,您会得到一个错误。

    两件事:

  • 与其他
    fn
    变体一样,您的基线捕获所有版本的
    fn
    也是一个很好的匹配;因此,充其量只能得到一个模糊的重载错误

  • >P>隐藏使用声明不考虑完整的签名(函数模板将包含模板参数列表)。它1)名称(2)(函数)参数类型列表,3)CV资格,和4)REF限定符(如果有的话)。如果四个都匹配,则基类函数模板将被隐藏,并且不会由using声明带入。值得注意的是,模板参数列表不会被考虑。在您的案例中,不同的
    fn
    s之间唯一不同的是模板参数列表;它们都具有相同的名称、相同的参数类型列表和相同的cv限定,和相同的ref限定符(或缺少)。因此,最派生的
    fn
    将隐藏基类中的所有
    fn
    s

    GCC似乎没有实现这一部分到规范,并在决定隐藏时考虑模板参数列表。

    此部分的一个可能修复方法是将
    enable_if
    移动到函数参数,隐藏检查会考虑该参数


    <> C++中的过载解决方法是:

  • 名称查找以构建一组候选函数和函数模板
  • 对于每个候选函数模板,执行模板参数推断。如果推断失败,则将其从重载集中删除。如果推断成功,则用推断的专用化替换候选函数模板
  • 从候选者集中删除不可行的候选者
  • 如果集合为空,则返回错误。否则,在候选函数中找到最佳可行函数
  • 隐藏操作在第一步:如果声明是隐藏的,则不会通过名称查找找到它,因此它不在候选的初始集合中,并且在任何情况下都不会通过重载解析进行考虑,无论在步骤2、3或4中发生了什么。隐藏声明实际上并不存在ad分辨率


    因此,在您的例子中,基类
    fn
    s都是隐藏的。这意味着什么?这意味着通过名称查找找到的唯一候选对象是来自最派生类的
    int
    ,而不是其他。如果模板参数推导和替换成功,则将调用该函数模板。如果失败(如
    x.fn(2.f)中所示)
    case),那么就没有可行的候选者了,你会得到一个错误。

    既然enable\u if\u t只在两件事上模板化,我不知道你为什么要用变量定义宏。@Nirfiedman,原因是可能有一个逗号会使宏
    #include <iostream>
    #include <type_traits>
    
    #define ENABLE_IF(...) std::enable_if_t<__VA_ARGS__, int> = 0
    
    
    template<typename T>
    struct always_false : std::false_type {};
    
    
    template<typename...Ts>
    struct list {};
    
    
    template<typename...Ts>
    struct is_one_of;
    
    template<template <typename...> class TT, typename T, typename T1, typename...Ts>
    struct is_one_of<T, TT<T1, Ts...>> : is_one_of<T, TT<Ts...>> {};
    
    template<template <typename...> class TT, typename T, typename...Ts>
    struct is_one_of<T, TT<T, Ts...>> : std::true_type {};
    
    template<template <typename...> class TT, typename T>
    struct is_one_of<T, TT<>> : std::false_type {};
    
    
    template<typename...Ts>
    struct X;
    
    template<typename L, typename T, typename...Ts>
    struct X<L, T, Ts...> : X<L, Ts...>
    {
        using X<L, Ts...>::fn;
    
        template<typename R, ENABLE_IF(std::is_same<T, R>::value)>
        constexpr auto fn(R&& x) const
        {
            return x;
        }
    };
    
    template<typename L>
    struct X<L>
    {
        template<typename R, ENABLE_IF(!is_one_of<R, L>::value)>
        constexpr auto fn(R&& x) const
        {
            static_assert(always_false<R>::value, "Type R didn't match");
        }
    };
    
    
    template<typename...Ts>
    struct XX : X<list<Ts...>, Ts...> {};
    
    int main()
    {
        XX<int, float> x;
        std::cout << x.fn(1) << std::endl;
        std::cout << x.fn(2.f) << std::endl;
    }