一个 TU 中的模板专业化被另一个 TU 隐藏
Template specialisation in one TU hidden by another TU
我有一个 class 模板 可以 specialised 以改变用户定义的效用函数的行为类型。
我有一个使用效用函数的翻译单元我的类型的专业可用。使用专业化。
在一个单独的翻译单元中,如果我在不包括专业化的情况下调用效用函数,它会改变另一个 TU 的行为(专业化在 both TU)
这是描述我的问题的完整示例:
check.h
: 定义了class模板,它可以专门用于用户定义的类型
#pragma once
#include <iostream>
template<typename T>
struct Check
{
static void type();
};
template<typename T>
void Check<T>::type()
{
std::cout << "check fall-back\n";
}
template<typename T>
void check(T&&)
{
Check<T>::type();
}
type.h
: 我自定义类型的定义
#pragma once
enum Foo
{
FOO,
BAR
};
type_check.h
: 专攻 Check
Foo
#pragma once
#include "type.h"
#include "check.h"
template<>
struct Check<Foo>
{
static void type()
{
std::cout << "check Foo\n";
}
};
lib.h
: TU头文件
#pragma once
void lib();
lib.cpp
: TU 源文件 - 使用来自 type_check.h
的专业化
#include "lib.h"
#include "type_check.h"
void lib()
{
check(FOO);
}
main.cpp
:
#include "check.h"
#include "type.h"
#include "lib.h"
#include "type_check.h" // uncomment this to make specialisation avail to all
int main()
{
check(5);
lib();
// check(FOO); // uncomment this to change behaviour of lib()`
return 0;
}
结果:
在 main
中调用 lib()
而不调用 check(FOO)
结果如下:
check fall-back
check Foo
在 main
中调用 lib()
和 check(FOO)
结果如下:
check fall-back
check fall-back <-- main changes behaviour of lib
check fall-back
在 main.cpp
中包含 type_check.h
,然后在 main
中调用 lib()
和 check(FOO)
结果如下:
check fall-back
check Foo
check Foo
问题:
为什么在 Check<Foo>
专业化不可用时在单独的 TU 中调用 check(FOO)
将其从 lib.cpp
中的重载集中删除?
备注:
我不能只将 Check<Foo>
特化与 Foo
的定义放在同一个文件中,因为 Foo
实际上是一个生成的文件 (protobuf)
这违反了单一定义规则。链接器看到同一个函数的两个函数定义,并会选择一个。不需要诊断。
在这种情况下,void Check<Foo>::type
由 lib.cpp 中使用的 check.h 模板定义的实例化定义一次,而另一个定义来自 type_check.h用于 main.cpp.
我有一个 class 模板 可以 specialised 以改变用户定义的效用函数的行为类型。
我有一个使用效用函数的翻译单元我的类型的专业可用。使用专业化。
在一个单独的翻译单元中,如果我在不包括专业化的情况下调用效用函数,它会改变另一个 TU 的行为(专业化在 both TU)
这是描述我的问题的完整示例:
check.h
: 定义了class模板,它可以专门用于用户定义的类型
#pragma once
#include <iostream>
template<typename T>
struct Check
{
static void type();
};
template<typename T>
void Check<T>::type()
{
std::cout << "check fall-back\n";
}
template<typename T>
void check(T&&)
{
Check<T>::type();
}
type.h
: 我自定义类型的定义
#pragma once
enum Foo
{
FOO,
BAR
};
type_check.h
: 专攻 Check
Foo
#pragma once
#include "type.h"
#include "check.h"
template<>
struct Check<Foo>
{
static void type()
{
std::cout << "check Foo\n";
}
};
lib.h
: TU头文件
#pragma once
void lib();
lib.cpp
: TU 源文件 - 使用来自 type_check.h
#include "lib.h"
#include "type_check.h"
void lib()
{
check(FOO);
}
main.cpp
:
#include "check.h"
#include "type.h"
#include "lib.h"
#include "type_check.h" // uncomment this to make specialisation avail to all
int main()
{
check(5);
lib();
// check(FOO); // uncomment this to change behaviour of lib()`
return 0;
}
结果:
在 main
中调用 lib()
而不调用 check(FOO)
结果如下:
check fall-back
check Foo
在 main
中调用 lib()
和 check(FOO)
结果如下:
check fall-back
check fall-back <-- main changes behaviour of lib
check fall-back
在 main.cpp
中包含 type_check.h
,然后在 main
中调用 lib()
和 check(FOO)
结果如下:
check fall-back
check Foo
check Foo
问题:
为什么在 Check<Foo>
专业化不可用时在单独的 TU 中调用 check(FOO)
将其从 lib.cpp
中的重载集中删除?
备注:
我不能只将 Check<Foo>
特化与 Foo
的定义放在同一个文件中,因为 Foo
实际上是一个生成的文件 (protobuf)
这违反了单一定义规则。链接器看到同一个函数的两个函数定义,并会选择一个。不需要诊断。
在这种情况下,void Check<Foo>::type
由 lib.cpp 中使用的 check.h 模板定义的实例化定义一次,而另一个定义来自 type_check.h用于 main.cpp.