【问题标题】:Declaration of methods with template arguments in implementation file在实现文件中声明带有模板参数的方法
【发布时间】:2019-01-24 09:09:27
【问题描述】:

是否有可能在不同的地方将类方法的定义和声明与模板参数(特别是在使用constexpr 函数时使用)分开?因为“模板参数”不是像模板函数的显式特化吗?

或者这种情况与已经讨论好的话题纠缠不清: Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?

Why can templates only be implemented in the header file?

例如: 头文件“someHeader.h”

#include <iostream>

#pragma once
class cc
{
public:
    cc()=default;
    ~cc()=default;

    template<uint32 f_val2Check_u32>
    constexpr uint32 isPowerOf2();

private:
};

然后是 *.cpp 文件:

// cpp-file
#include "someHeader.h"

template<uint32 val>
constexpr uint32 cc::isPowerOf2()
{
    return ((val&(val-1))==0);
}

【问题讨论】:

  • 基本上没有。原因是调用代码实际上是通过填充它进行调用的类型来生成函数体。所以编译器需要看到模板主体,而不仅仅是签名。 (当然会有办法解决这个问题,但这是 20 多年前设计规则时的动机)。

标签: c++ c++11 templates c++14 constexpr


【解决方案1】:

问题是模板在编译时被实例化。

因此,它需要查看函数或类的定义,以了解所有操作类将应用于所传递的类型。

让我们在你的函数声明中说: template &lt;typename T&gt; void print_square(T t)
看到这个,你能说出什么:
"所有操作将应用于T 类型"?
老实说,什么都没有。

现在让我们看看函数定义:

template <typename T>
void print_square(T t)
{
    std::cout << t * t; 
}

现在,当我们看到函数定义时,我们可以看出二元运算符 * 应该适用于类型 T
这是传递给模板的类型要求
换句话说,操作类适用于 T 类型被传递。

因此,编译器需要访问函数模板的函数定义。
它可以阻止您将std::string 作为参数传递给print_square(),因为它不符合要求。

【讨论】:

    【解决方案2】:

    编译器必须知道函数在使用它的所有翻译单元中的实现方式。 constexpr 关键字告诉编译器在编译时计算给定参数的函数结果并传播该值。没有实现,这是无法实现的。

    这适用于非模板非 constexpr 函数,因为该值可以在运行时计算,即在链接之后。

    【讨论】:

      猜你喜欢
      • 2012-01-06
      • 2010-12-20
      • 1970-01-01
      • 1970-01-01
      • 2011-07-09
      • 1970-01-01
      • 2021-09-14
      • 2021-05-28
      • 2017-12-22
      相关资源
      最近更新 更多