【问题标题】:Template partial specialization with multiple template argument error具有多个模板参数错误的模板部分特化
【发布时间】:2011-12-14 10:42:34
【问题描述】:

当我在一个带有一个模板参数的类上使用模板部分特化时,我可以像这样特化一个方法:

#include <cstdlib>

template< std::size_t Dim >
class Test
{
public:
  int foo();
};

template< std::size_t Dim >
inline int Test< Dim >::foo()
{
  return 0;
}

template<>
inline int Test< 1 >::foo()
{
  return 1;
}

int main()
{
  Test< 2 > wTest2;
  Test< 1 > wTest1;
  wTest2.foo();
  wTest1.foo();
  return 0;
}

方法 foo 专门用于 Dim = 1。但只要我向我的类添加模板参数,就像这样:

#include <cstdlib>

template< typename T, std::size_t Dim >
class Test
{
public:
  int foo();
};

template< typename T, std::size_t Dim >
inline int Test< T, Dim >::foo()
{
  return 0;
}

template< typename T >
inline int Test< T, 1 >::foo()
{
  return 1;
}

int main()
{
  Test< double, 2 > wTest2;
  Test< double, 1 > wTest1;
  wTest2.foo();
  wTest1.foo();
  return 0;
}

编译器(VS2010)报错:

1>c:\documents and settings\cayouette\my documents\codelocal\testtemplatespecialization\main.cpp(20): error C3860: template argument list following class template name must list parameters in the order used in template parameter list
1>c:\documents and settings\cayouette\my documents\codelocal\testtemplatespecialization\main.cpp(20): error C2995: 'int Test<T,Dim>::foo(void)' : function template has already been defined
1>          c:\documents and settings\cayouette\my documents\codelocal\testtemplatespecialization\main.cpp(7) : see declaration of 'Test<T,Dim>::foo'
1>c:\documents and settings\cayouette\my documents\codelocal\testtemplatespecialization\main.cpp(20): error C2976: 'Test<T,Dim>' : too few template arguments
1>c:\documents and settings\cayouette\my documents\codelocal\testtemplatespecialization\main.cpp(26): error C2264: 'Test<T,Dim>::foo' : error in function definition or declaration; function not called
1>          with
1>          [
1>              T=double,
1>              Dim=2
1>          ]
1>c:\documents and settings\cayouette\my documents\codelocal\testtemplatespecialization\main.cpp(27): error C2264: 'Test<T,Dim>::foo' : error in function definition or declaration; function not called
1>          with
1>          [
1>              T=double,
1>              Dim=1
1>          ]
1>
1>Build FAILED.

在我看来,没有歧义,编译器应该能够解决所有问题,并且就像一个参数的情况一样工作。

如果 C++ 不支持,请解释原因。

【问题讨论】:

  • 这个FAQ问题的重复:stackoverflow.com/questions/1501357/…
  • 谢谢约翰内斯,我确实为这种答案寻找了几个小时但没有成功。话虽如此,我的问题有点不同,我在问为什么它不起作用,到目前为止,我还没有一个明确的答案。

标签: c++ templates compiler-errors metaprogramming partial-specialization


【解决方案1】:

你不能部分特化函数——这包括成员函数。你只能部分特化整个类

template< typename T, std::size_t Dim >
class Test
{
public:
  int foo()
  {
    return 0;
  }
};

template< typename T >
class test< T, 1 >
{
public:
  int foo()
  {
    return 1;
  }
};

(我在这里定义了内联函数;这当然不是必需的。)

【讨论】:

  • 好的,带有一个模板参数的示例应该被称为 full 特化,而不是部分;这可能就是它起作用的原因。但是,我看不出成员函数不支持偏特化的任何原因,您能解释一下原因吗?编译器是否有歧义或约束?
  • @Philippe 我不确定为什么部分函数模板被禁止(但它们实现的目标通常可以通过重载来解决)。但是,请查看 regu 的答案,因为我的解释实际上是错误的,您并没有部分专门化成员函数。尽管如此,由于一些微妙的原因,您使用的语法是无效的(您正在为一个部分特化的类定义一个成员函数,但您实际上并没有首先对这个类进行部分特化)。
  • regu 建议的是我首先实现的,因为我不知道 Johannes Schaub (stackoverflow.com/questions/1501357/…) 指出的重载技巧
【解决方案2】:

编辑因为我还不能发布 cmets (50 rep heh)...

Philippe,针对您今天上午的评论,根据标准,您不能部分特化类模板的成员,您只能完全特化它们(无论是类模板、函数、函数模板等) ...)。在您的第一个示例中,您完全专门化了成员函数 foo。在您的第二个示例中,您部分专业化,原因是它无法编译。您可以通过这种方式对其进行完全专业化:

template< >
inline int Test< int, 2 >::foo()
{...}

虽然 Konrad 的代码片段完全合法,但我不确定 Philippe 的代码无法编译的原因是否正确。 (尽管,正如 Konrad 提到的,您不能部分特化函数模板)。

在 Philippe 的代码中,手头的问题是我们声明的是类模板而不是函数模板。因此,为了使部分特化定义合法,需要部分类模板特化声明。

#include <cstdlib>

template< typename T, std::size_t Dim >
class Test
{
public:
    int foo();
};

template < typename T >
class Test < T, 1 >
{
public:
    int foo();
};


template< typename T, std::size_t Dim >
inline int Test< T, Dim >::foo()
{
    return 0;
}

template< typename T >
inline int Test< T, 1 >::foo()
{
    return 1;
}

int main()
{
    Test< double, 2 > wTest2;
    Test< int, 1 > wTest1;
    wTest2.foo();
    wTest1.foo();
    return 0;
}

【讨论】:

    猜你喜欢
    • 2011-06-10
    • 1970-01-01
    • 2012-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    • 1970-01-01
    • 2022-01-21
    相关资源
    最近更新 更多