【问题标题】:template overloading and SFINAE working only with functions but not classes模板重载和 SFINAE 仅适用于函数而不适用于类
【发布时间】:2012-02-23 04:25:12
【问题描述】:

谁能解释一下为什么编译器只接受这段代码

template<typename L, size_t offset, typename enable_if< (offset<sizeof(L)), int >::type =0>
void a_function(){}

template<typename L, size_t offset, typename enable_if< (offset==sizeof(L)), int >::type =0>
void a_function(){}

但不是这个:

template<typename L, size_t offset, typename enable_if< (offset<sizeof(L)), int >::type =0>
class a_class{};

template<typename L, size_t offset, typename enable_if< (offset==sizeof(L)), int >::type =0>
class a_class{};

编译器将第二个类模板视为对第一个类模板的重新定义。

【问题讨论】:

  • 哦,&lt; 之前的sizeof 让我的大脑受伤了^_^

标签: c++ templates c++11 sfinae


【解决方案1】:

您必须对课程使用专业化。通常,它是通过一个额外的参数来完成的:

template <class P, class dummy = void>
class T;

template <class P>
class T<P, typename enable_if<something, void>::type> {
   the real thing
};

两个同名的类(或类模板)声明应该总是声明同一个类或类模板(或者是一个特化,在这种情况下它仍然是同一个模板)。

【讨论】:

  • something 为真时,typename enable_if&lt;something, int&gt;::type = 0 等价于int __anonymous_param = 0
  • 但是为什么功能成功了?
  • @LightnessRacesinOrbit 因为您可以重载函数,但不能重载类型。在函数版本中,您定义了两个潜在的重载(针对不同的类型集),而在第二种情况下,您定义了两个具有相同名称的模板,这是无法完成的。两个函数同名就好(只要不产生歧义),两个类型同名,不是那么好,即使它们实际上是类型模板。
  • @LightnessRacesinOrbit 因为函数可以重载。并且模板化的函数根据 SFINAE 被重载。
  • @LightnessRacesinOrbit:我会说这是因为两个同名的函数定义仍然是两个函数定义,但是两个类(类模板)定义总是同一个类/模板。
【解决方案2】:

你可能想做这样的事情 (ideone.com link):

#include <iostream>

template< typename PL, size_t pOffset, int pC = int( sizeof(PL) ) - int( pOffset ) >= 0 ? ( int( sizeof(PL) ) - int( pOffset ) == 0 ? 0 : 1 ) : -1 >
class TClass
{
};

template< typename PL, size_t pOffset >
class TClass< PL, pOffset, -1 >
{
 public:
  static int const sI = -1;
};

template< typename PL, size_t pOffset >
class TClass< PL, pOffset, 0 >
{
 public:
  static int const sI = 0;
};

template< typename PL, size_t pOffset >
class TClass< PL, pOffset, 1 >
{
 public:
  static int const sI = 1;
};

int main(void )
{
 TClass< char, 0 > lC0;
 TClass< char, 1 > lC1;
 TClass< char, 2 > lC2;

 std::cout << lC0.sI << " : " << lC1.sI << " : " << lC2.sI << std::endl;

 return ( 0 );
}

程序输出:

1 : 0 : -1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-03
    • 2017-02-23
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    相关资源
    最近更新 更多