如何使用is_base_of专门化模板,而不会与主模板产生歧义
How can I specialize a template using is_base_of without being ambiguous with the primary template?
使用下面的代码,我收到编译器抱怨对get_code调用在前两个模板之间模棱两可。 如何编写代码以检测基类,同时提供专用表单? 例如,如果以后我有class C : A {}
它也应该返回ACLASS
.
class A {};
class B : A {};
class D {};
enum Code { UNKNOWN, ACLASS, DCLASS };
template <typename T>
Code get_code() { return Code::UNKNOWN; }
template <typename T>
typename std::enable_if<std::is_base_of<A, T>::value, Code>::type
get_code() { return Code::ACLASS; }
template <>
inline Code get_code<D>() { return Code::DCLASS; }
Code test1 = get_code<D>(); // OK, chooses DCLASS
Code test2 = get_code<B>(); // ambiguous call to overloaded function
当T
是A
的基数时,您必须停用未知情况
template <typename T>
typename std::enable_if< ! std::is_base_of<A, T>::value, Code>::type
get_code() // -----------^
{ return Code::UNKNOWN; }
否则,当T
是A
的基础时,编译器可以使用两个版本的get_code()
而不能选择正确的版本(不明确的调用(
以下是完整的工作示例
#include <iostream>
#include <type_traits>
class A {};
class B : A {};
class C {};
class D {};
enum Code { UNKNOWN, ACLASS, DCLASS };
template <typename T>
typename std::enable_if<!std::is_base_of<A, T>::value, Code>::type
get_code()
{ std::cout << "code U" << std::endl; return Code::UNKNOWN; }
template <typename T>
typename std::enable_if<std::is_base_of<A, T>::value, Code>::type
get_code()
{ std::cout << "code A" << std::endl; return Code::ACLASS; }
template <>
Code get_code<D>()
{ std::cout << "code D" << std::endl; return Code::DCLASS; }
int main()
{
get_code<A>(); // print A
get_code<B>(); // print A
get_code<C>(); // print U
get_code<D>(); // print D
}
但是我建议您使用另一种方法,基于标签调度,在不使用SFINAE的情况下获得相同的结果
#include <iostream>
#include <type_traits>
class A {};
class B : A {};
class C {};
class D {};
enum Code { UNKNOWN, ACLASS, DCLASS };
Code gc2h (std::true_type const &)
{ std::cout << "code A" << std::endl; return Code::ACLASS; }
Code gc2h (std::false_type const &)
{ std::cout << "code U" << std::endl; return Code::UNKNOWN; }
template <typename T>
Code gc2 ()
{ return gc2h(typename std::is_base_of<A, T>::type {}); }
template <>
Code gc2<D>()
{ std::cout << "code D" << std::endl; return Code::DCLASS; }
int main()
{
gc2<A>(); // print A
gc2<B>(); // print A
gc2<C>(); // print U
gc2<D>(); // print D
}
另一种方法是将 std::is_base_of
的值作为帮助程序函数的模板参数传递
#include <iostream>
#include <type_traits>
class A {};
class B : A {};
class C {};
class D {};
enum Code { UNKNOWN, ACLASS, DCLASS };
template <bool>
Code gc3h ();
template <>
Code gc3h<true> ()
{ std::cout << "code A" << std::endl; return Code::ACLASS; }
template <>
Code gc3h<false> ()
{ std::cout << "code U" << std::endl; return Code::UNKNOWN; }
template <typename T>
Code gc3 ()
{ return gc3h<std::is_base_of<A, T>::value>(); }
template <>
Code gc3<D>()
{ std::cout << "code D" << std::endl; return Code::DCLASS; }
int main()
{
gc3<A>(); // print A
gc3<B>(); // print A
gc3<C>(); // print U
gc3<D>(); // print D
}
--编辑--
另一种可能的解决方案。
如果你能接受你的函数是模板class
(或struct
(的static
方法,并且如果你能接受它被称为gc4<T>::func()
而不是gc4<T>()
,那么基于部分特化的另一种方式,可以遵循。
#include <iostream>
#include <type_traits>
class A {};
class B : A {};
class C {};
class D {};
enum Code { UNKNOWN, ACLASS, DCLASS };
template <typename T, bool = std::is_base_of<A, T>::value>
struct gc4;
template <typename T>
struct gc4<T, true>
{
static_assert(true == std::is_base_of<A, T>::value, "!");
static Code func ()
{ std::cout << "code A" << std::endl; return Code::ACLASS; }
};
template <typename T>
struct gc4<T, false>
{
static_assert(false == std::is_base_of<A, T>::value, "!!");
static Code func ()
{ std::cout << "code U" << std::endl; return Code::UNKNOWN; }
};
template <>
struct gc4<D>
{
static Code func ()
{ std::cout << "code D" << std::endl; return Code::DCLASS; }
};
int main()
{
gc4<A>::func(); // print A
gc4<B>::func(); // print A
gc4<C>::func(); // print U
gc4<D>::func(); // print D
}
添加static_assert()
是为了避免有人可以绕过调用类似
gc4<A, false>::func();
相关文章:
- 构造对象的歧义
- Usages of std::move
- 使用 [] 运算符时"binding reference of type discards qualifiers"
- 如何处理 c++ 中类实现中的"invalid use of non-static data member"?
- 我知道函数调用中存在歧义.有没有办法调用foo()函数
- 具有变量Number of Arguments的std::函数的矢量
- Capacity of a deque
- Deprecation of _writeBarrier()
- constexpr begin of a std::array
- 如何调整 std::vector of Eigen::MatrixXd 的大小
- C++ "error: invalid use of void expression"
- 我看到"use of undeclared identifier"错误,有人可以告诉我如何解决它吗?
- 赛通"Cannot take address of memoryview slice"
- C++ Version Of Double.longBitsToDouble
- 收到错误"invalid use of non-static data member 'stu::n' "
- C++ Usage of AsyncCallback
- 错误:"Left of getValue must have class/struct/union"
- Centos7 g++ "to_string is not in a member of std"
- 在C++中使用 Catch 测试框架编译错误"error: expected ';' at end of declaration list"
- 数组初始值设定项的构造函数歧义