对专用模板成员的未定义引用
Undefined reference to specialized template member
我有一个由具有静态成员函数的模板模板类参数化的类:
template <template <typename> class F>
struct A {
static int foo();
};
这个类没有foo
的默认定义,必须专门用于不同的类型。
我还有另一个由带有嵌套模板类的模板模板类参数化的类:
template <template <typename> class F>
struct B {
template <typename T>
struct C {};
};
我希望C
专门针对任何专门A
的模板模板类F
专门A
:
template <template <typename> class F>
struct A<B<F>::template C> {
static int foo();
};
template <template <typename> class F>
int A<B<F>::template C>::foo() {
return A<F>::foo() / 2;
}
因此,如果我有一个专门A
的课程:
template <typename T>
struct E {};
template <>
int A<E>::foo() {
return 42;
}
我希望能够像这样使用专业化(并返回 21(:
int bar() {
return A<B<E>::template C>::foo();
}
但是,这无法链接 - 它找不到对A<B<E>::C>::foo()
的引用。
(请注意,所有这些都在一个文件中 - 这里的标头没有什么奇怪的事情发生(
编译器似乎正在尝试使用主模板进行A
而不是专用化,这意味着foo
未定义。为什么在这种情况下不使用专业化?
完整示例
template <template <typename> class F>
struct A {
static int foo();
};
template <template <typename> class F>
struct B {
template <typename T>
struct C {};
};
template <template <typename> class F>
struct A<B<F>::template C> {
static int foo();
};
template <template <typename> class F>
int A<B<F>::template C>::foo() {
return A<F>::foo() / 2;
}
template <typename T>
struct E {};
template <>
int A<E>::foo() {
return 42;
}
int bar() {
// Link fails - error: undefined reference to 'A<B<E>::C>::foo()'
return A<B<E>::template C>::foo();
}
template<class T>
struct A {};
template<class T>
struct B {
using type=T;
};
template<class T>
struct A<typename B<T>::type> {};
这基本上相同,但模板层少了 1 个。
这也行不通。
问题在于,在一般情况下,B<T>::type
或B<T>::template Z
或其他任何东西都是任意编译时函数。
为了与它进行模式匹配,我们需要反转这个任意编译时函数。
该标准说"编译器不必这样做",这是您可以在这里做的为数不多的理智的事情之一。 对于类型,它肯定是这样说的;对于模板,嗯,模板模板参数的标准措辞经常缺少细节,所以如果缺少措辞,我不会感到惊讶。 但如果它不这样做,那将是标准中的一个错误。
为了从
template<class T>
struct A<typename B<T>::type> {};
要查看A<foo>
是否匹配它,它必须测试所有类型的T
以查看其中哪些类型的B<T>::type
等于foo
.
这可能不是你打算问的,但这就是你要问的。
模板示例也是如此。
template <template <typename> class F>
struct A<B<F>::template C> {
static int foo();
};
您要求编译器检查每种类型F
以便将其传递给任意模板B<>
然后在其中::C
进行计算,该模板是否与您传递A
的内容匹配。
第一个有趣的案例:
template<class X>
struct C0 {};
template <template <typename> class F>
struct B {
template <typename T>
using C=C0<X>:
};
现在,A<C0>
F
是什么? 每个F
都有资格。
template<class X>
struct C0 {};
template <template <typename> class F, class=void>
struct B {
template <typename T>
using C=C0<X>:
};
template<class X>
struct C1 {};
template <template <typename> class F, class=void>
struct B<
F,
std::enable_if_t<
proves_collatz_conjecture( F<int>::value )
>
> {
template <typename T>
using C=C1<T>;
};
现在,为了A<C0>
模式,编译器必须生成F
,以便F<int>::value
是一个编译时类型,当传递给proves_collatz_conjecture
时,在编译时返回true
。
那将是有用的。
模板专用化是模式匹配。 在C++中,您无法与依赖类型(大概是模板(进行模式匹配,因为类型和模板都没有超出其值的标识。
您无法检查定义变量、类型或模板的范围。 所以你也无法匹配模式。
如果要执行所需的操作,则模板C
本身必须具有可以检查和测试的属性。
- 对C宏的未定义引用,但在定义它时会出现重新定义错误
- 编译时的 CImg 库返回对"__imp_SetDIBitsToDevice"的未定义引用
- 对Py_Initialize()的未定义引用
- 使用mysql c++连接器的未定义引用
- 对 Scalar ::Scalar() 的未定义引用
- 对复制 CTOR 和 CTOR 的未定义引用
- 对显式实例化的模板函数的未定义引用
- TensorRT (C++ API) 对"createNvOnnxParser_INTERNAL"的未定义引用
- 2个模板化类的非模板友元函数未定义引用错误
- 编译 libfluid 样本控制器时对"event_base_del_virtual"的未定义引用
- 获取对function_name的未定义引用
- 对 'std::thread::_M_start_thread CMake 的未定义引用进行基准测试
- 对结构方法的未定义引用
- 使用内联函数 c++ 的未定义引用
- 对 CMake 中'cudaRegisterLinkedBinary'链接错误的未定义引用?
- 对 DLOPEN 的未定义引用
- QT C++中对全局变量的未定义引用
- 快速数学导致对"__pow_finite"的未定义引用
- 对 boost::system::d etail::system_category_instance 的未定义引用,从
- OpenCV 3.4.3 中对 'cv::String::d eallocate()' 错误的未定义引用