【问题标题】:Does static data member specialization in CRTP violate ODR?CRTP 中的静态数据成员特化是否违反 ODR?
【发布时间】:2021-11-29 06:06:55
【问题描述】:

首先,我知道这个问题可能看起来是重复的。但是我已经阅读了很多类似问题的帖子,但没有找到答案。

其次,到目前为止,我的解决方案没有任何问题。所以我要问的是我的解决方案是否是一个没有缺陷的正确解决方案。

假设我有一个类模板Particle,它应该是CRTP 中的一个基类,并打算有一个静态变量fName,它可能因实例而异

基础

粒子.h

#pragma once

#include <iostream>
#include <string>

template<typename CONCRETE_PARTICLE>
class Particle
{
    private :
        static const std::string fName;

    public :
        static const std::string& GetName() { return fName; }
};

// Default name. If I'm not mistaken this is fine regarding ODR.
template<typename CONCRETE_PARTICLE>
const std::string Particle<CONCRETE_PARTICLE>::fName = "Unknown";

所以其他粒子从这个类继承(和实例化)。假设用户创建了一个新的Particle,他们应该可以选择是否指定新粒子的名称。在后一种情况下,名称将是 "Unknown"

未命名的粒子

Tachyon.h

#pragma once

#include "Particle.h"

class Tachyon : public Particle<Tachyon>
{
    public :
        Tachyon();
        ~Tachyon() = default;
};

Tachyon.cpp 没有什么特别之处(我制作了.cpp 文件以检查是否违反了 ODR)。

另一方面,如果要指定名称怎么办。他们应该怎么做?

命名粒子

介子.h

#pragma once

#include "Particle.h"

class Muon : public Particle<Muon>
{
    public :
        Muon();
        ~Muon() = default;

};

// Specification declaration (???)
// Tell the compiler that Particle<Muon>::fName is defined somewhere
// and not to take the default value into account (???)
template<>
const std::string Particle<Muon>::fName;

介子.cpp

#include "Muon.h"

Muon::Muon() {}

template<>
const std::string Particle<Muon>::fName = "Muon";

Main.cpp

#include "Muon.h"
#include "Tachyon.h"

int main()
{
    std::cout << Particle<Muon>::GetName() << "\n"; // prints "Muon"
    std::cout << Particle<Tachyon>::GetName() << "\n"; // prints "Unknown"
    return 0;
}

正如我所说,我没有收到任何错误,程序按预期运行。但是我对 CRTP + ODR + 静态数据成员声明/定义的组合有点困惑。

【问题讨论】:

  • 我投票结束这个问题,因为这应该在 softwareengineering.stackexchange.com 上提问。
  • 您可能想要删除那些默认的析构函数,因为它们会禁用编译器生成的移动构造函数/赋值:stackoverflow.com/questions/56968443/…
  • @AVH,谢谢。会考虑的。
  • @cse 我不明白这与软件工程有什么关系。据我所知,这严格来说是一个与 ODR 相关的 C++ 问题。标题与问题有点不同,所以我已经编辑了它。
  • @cse 我不知道这个问题是否适合软件工程,但它绝对是本网站的主题。即使它适用于其他网站,也不是关闭问题的理由。

标签: c++ templates static crtp explicit-instantiation


【解决方案1】:

目前尚不清楚您认为这可能违反什么规则,但该程序格式正确。特别是,模板化静态变量的显式特化只有在它们具有初始化程序([temp.expl.spec]/14)时才是定义。 (非成员变量模板使用extern 来仅声明特化。)只要派生类不这样做,在显式特化被声明之前也不会使用主模板。

也就是说,您可以很容易地完全避免在这里使用专业化:使用 SFINAE 检测 成员 fName,如果没有则返回"Unknown"。或者只是查找fNameCONCRETE_PARTICLE::fName 以使用那里声明的任何内容。 (顺便提一下,模板参数不要使用MACRO_NAMES。)

【讨论】:

    猜你喜欢
    • 2013-09-25
    • 1970-01-01
    • 2021-06-19
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-20
    • 1970-01-01
    相关资源
    最近更新 更多