当前位置: 首页 > 知识库问答 >
问题:

成员函数模板选择与SFINAE

昝成弘
2023-03-14

我一直试图理解C++选择模板的方式。即,考虑以下代码示例:

template <typename R>
class Curious
{
public:
    template <typename T, typename std::enable_if<std::is_const<T>::value, int>::type = 33>
    void test1() {}

    template <typename T, typename std::enable_if<!std::is_const<T>::value, int>::type = 33>
    void test1() {}

    template <typename T, typename = typename std::enable_if<std::is_const<T>::value>::type>
    void test2() {}

    template <typename T, typename = typename std::enable_if<!std::is_const<T>::value>::type>
    void test2() {}

    template <typename std::enable_if<std::is_const<R>::value>::type * = nullptr>
    void test3() {}

    template <typename std::enable_if<!std::is_const<R>::value>::type * = nullptr>
    void test3() {}

    // works
    template <typename T = void>
    typename std::enable_if<std::is_const<R>::value, T>::type test4() {}

    template <typename T = void>
    typename std::enable_if<!std::is_const<R>::value, T>::type test4() {}

    // also works
    template <typename T = void, typename std::enable_if<std::is_const<R>::value, T>::type * = nullptr>
    void test5() {}

    template <typename T = void, typename std::enable_if<!std::is_const<R>::value, T>::type * = nullptr>
    void test5() {}
}; // Curious

前两个函数(test1)工作正常(为什么?):

Curious<int> curious;
curious.test1<int>();
curious.test1<const int>();
error C2535: 'void Curious::test2(void)': member function already defined or declared

一个常见的错误是声明两个仅在默认模板参数上不同的函数模板。这是非法的,因为默认模板参数不是函数模板签名的一部分,并且用相同的签名声明两个不同的函数模板是非法的。

所以看起来是这样的。但是,我看不出与前两个函数有太大的不同,前两个函数也有默认的模板参数。因此,我们对默认值(test1-works)有一个默认类型(test2-不工作)。对此有什么规定吗?

在Test3的情况下:

error C2039: 'type': is not a member of 'std::enable_if'

我对C++如何处理这些模板很困惑。有人能这么好心把这些事情弄清楚吗?

共有1个答案

濮阳唯
2023-03-14

>

  • 删除默认值后,对于test1,您有:

    template <typename T, typename std::enable_if<std::is_const<T>::value, int>::type>
    void test1();
    
    template <typename T, typename std::enable_if<!std::is_const<T>::value, int>::type>
    void test1();
    

    有明显不同的签名。

    对于测试2:

    template <typename T, typename> void test2();
    
    template <typename T, typename> void test2();
    
    int foo();
    char foo(); // Illegal.
    
    template <typename T> int foo();
    template <typename T> char foo(); // legal, even it is not trivial to call
    

    对于test5,第二个模板参数依赖于第一个模板参数t,所以也可以。

  •  类似资料:
    • 我有一个模板化的C++类,它也有一个模板化的成员函数。这个成员函数的模板参数以特定的方式依赖于类的模板参数(请参阅下面的代码)。我正在为其模板参数的两个不同值实例化(而不是专门化)该类。一切都在这一点上进行。但是,如果我调用模板化的成员函数,对第一个实例化对象的调用只会编译,而不会编译第二个。似乎编译器没有为模板类的第二次实例化实例化模板化成员函数。我正在使用“g++filename.cpp”编译

    • 以下SSCCE说明了这种情况: 项目之前编译得很好,我用几个编译器(、、、和)再次检查了这个SSCCE,所有这些编译器都在没有任何警告的情况下编译了它(使用)。所有编译器都设置为C++11/C++0x标准。将ctor添加到中后,即使在和上也能很好地编译 使两个的非成员都显示了所有编译器中的二义性(正如预期的那样) 在查看了标准草案(和)之后,我没有找到任何使成员函数/运算符比非成员函数/运算符更匹

    • 是否有人知道此显式特化是否有效: clang 主干 (12/3/2013) 给出以下错误: f:...\test.cpp:36:20: 错误: 从类 'O' 中出线定义 “Fun” 没有定义 1生成错误。 任何来自标准的支持参考来证明你的答案将不胜感激! 注意:我有点惊讶这是一个错误——我认为应该为任何以< code >开始实例化“Fun”的模板参数族选择专门化 这是一个叮当的错误还是我期望中的错

    • 在非模板类中,类的所有对象共享一个 static 数据成员,Static 数据成员应在文件范围内初始化。 从类模板实例化的每个模板类有自己的类模板 static 数据成员,该模板类的所有对象共享一个 Static 数据成员。和非模板类的 static 数据成员一样,模板类的 static 数据成员也应在文件范围内初始化。每个模板类有自己的类摸板的 static 数据成员副本。

    • 我有一个问题,我想在下面的代码中专门化模板类的模板成员函数。这个问题的答案是模板类成员函数的显式特化,这似乎表明它无法完成。这是正确的吗,如果是这样,我可以使用任何解决方法,以便在编译时通过内联inc函数进行扩展? 非常感谢! g吐槽道: test2.cpp:32:13: 错误: 非命名空间作用域中的显式专用化 'struct IdxIterator' test2.cpp:32:25: 错误: 非

    • 我有以下模板方法: 但是我得到了那些奇怪的链接错误: /usr/lib/gcc/x86_64-redhat-linux/4.4。7/../../../../包括/c/4.4。7/例外:62:void MyStruct::readField(std::basic_istream)的多重定义 如何专门化此成员函数? 编辑 这种方法在以下方面起作用: 或者使用s或在类外使用