首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在类定义之外用enable_if实现函数

在类定义之外用enable_if实现函数
EN

Stack Overflow用户
提问于 2018-01-27 20:56:09
回答 6查看 2.9K关注 0票数 9

因此,基本上,我现在有一个非常基本的泛型类,目前正在测试type_traits头。目前,我正在尝试制作一个函数来处理某些类型的函数,即目前使用的算术函数。

代码语言:javascript
复制
#include <type_traits>

template <typename T> class Test {
    public:
        template <typename U = T> 
        typename std::enable_if<std::is_arithmetic<U>::value>::type print();
}; 

该函数工作良好,仅适用于算术类型。

但我喜欢保持类的整洁,只让它们具有原型,而函数实现则在类之外。

使用标准模板,例如

代码语言:javascript
复制
void test();

template <typename T> void Test<T>::test() {}

这很简单,我知道如何做,但是我不知道如何用"std::enable_if“来声明类之外的实现,我在编译过程中所做的每一次尝试都说原型与类中的任何一个都不匹配。

我在这里找到了一个类似的问题,但是那里的类是标准的,而不是泛型的。

PS。我在-std=c++17中使用MinGW-w64

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2018-01-27 21:04:07

类模板需要一组模板参数,成员函数模板需要一组单独的模板参数。您需要重复整个复杂的返回类型,因为它是函数模板签名的一部分。请注意,您不能重复默认参数=T,否则编译器会认为您试图两次定义它(而不检查新定义是否相同)。

代码语言:javascript
复制
template <typename T> template <typename U>
typename std::enable_if<std::is_arithmetic<U>::value>::type
Test<T>::print()
{
    // Implementation here.
}

顺便说一句,您使用的是编写类型的“漫长的方式”,这在C++11中是需要的,但是C++14引入了std::enable_if_t快捷方式,C++17引入了std::is_arithmetic_v快捷方式。因此,如果使用C++17,还可以编写以下类型

代码语言:javascript
复制
typename std::enable_if<std::is_arithmetic<U>::value>::type

就像

代码语言:javascript
复制
std::enable_if_t<std::is_arithmetic_v<U>>
票数 9
EN

Stack Overflow用户

发布于 2018-01-27 21:40:22

如果您将enable_if放在默认的模板参数中,这是imo更好的,那么类外定义就会变得更容易一些:

代码语言:javascript
复制
template<typename T>
struct Test
{
    template <typename S = T
            , typename = typename std::enable_if<std::is_arithmetic<S>::value>::type >
    void print();
};

template<typename T>
template<typename S, typename>
void Test<T>::print()
{
    //some code
}
票数 5
EN

Stack Overflow用户

发布于 2018-01-27 21:02:57

你可以试试

代码语言:javascript
复制
template <typename T>
template <typename U>
std::enable_if_t<std::is_arithmetic<U>::value> Test<T>::print()
 { /* do something */ }

下面是一个完整的工作示例

代码语言:javascript
复制
#include <iostream>
#include <type_traits>

template <typename T> class Test
 {
   public:
      template <typename U = T>
      std::enable_if_t<std::is_arithmetic<U>::value> print();
 }; 

template <typename T>
template <typename U>
std::enable_if_t<std::is_arithmetic<U>::value> Test<T>::print()
 { std::cout << "test!" << std::endl; }

int main ()
 {
   Test<int>  ti;
   Test<void> tv;

   ti.print();   // compile
   //tv.print(); // compilation error
 }

离题1

请注意,您的解决方案可能以这种方式被劫持。

代码语言:javascript
复制
Test<void>{}.print<int>(); 

为了避免这个问题,您可以强制要求T等于U

代码语言:javascript
复制
template <typename T> class Test
 {
   public:
      template <typename U = T>
      std::enable_if_t<   std::is_arithmetic<U>::value
                       && std::is_same<T, U>::value> print()
       { }
 }; 

离题2

如您所见,您必须重复SFINAE部分(std::enable_if_tstd::is_arithmeticstd::is_same)。

考虑到您必须在标题中重复实现,我不认为(IMHO)在类的主体之外编写模板类的实现是一个好主意。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48480469

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档