我可以在模板参数扣除期间获得转换吗?
Can I get a conversion during template argument deduction?
我这里有这段代码:
#pragma once
using uInt = size_t;
template<uInt id> class idType {};
template<typename T> class typeId {};
#define Generate_Type_To_ID_Mapping(id, t)
class t;
template<>class idType<id> { public: using type = t; };
template<>class typeId<t> { public: operator uInt() { return val; }
typeId() = default;
typeId(typeId const&) = delete;
typeId& operator=(typeId const&) = delete;
typeId(typeId&&) = delete;
typeId& operator=(typeId&&) = delete;
static constexpr uInt val = id;
};
Generate_Type_To_ID_Mapping(0, Entity);
Generate_Type_To_ID_Mapping(1, RectComponent);
Generate_Type_To_ID_Mapping(2, ConstraintComponent);
Generate_Type_To_ID_Mapping(3, TextComponent);
这是一个宏,它为每个给定的<size_t, T>
集制造 2 个模板专用化,一个模板从类型到索引的转换,另一个模板从索引到类型的转换。 它们被称为:
// type to index:
typeId<RectComponent>() // the conversion operator returns
// the value mapped to this type
// index to type:
idType<2>::type // type is an alias to the mapped type
它们本身工作正常,但是如果我尝试将一个放在另一个内部idType<typeId<RectComponent>()>::type
则代码将无法编译,我怀疑这是因为模板参数推断没有尝试任何转换(typeId<>()
依赖于operator uInt()
(
我有办法让它operator uInt()
在模板参数推断期间被视为一种选择?
任何可以被视为函数声明的东西,编译器都会解析为函数声明。这被称为最令人烦恼的解析。typeId<RectComponent>()
可以被视为函数声明:返回typeId<RectComponent>
并接受参数的无名称函数。
这就是为什么你在idType<typeId<RectComponent>()>::type
中得到一个错误:编译器尝试使用函数类型作为模板参数实例化idType
模板。
等效代码为:
using T = typeId<RectComponent>(); // this line is OK, T is a function type
using Type = idType<T>::type; // error is here
由于完全相同的原因,此等效代码无法编译
using Type = idType<typeId<RectComponent>()>::type;
不编译。
你想要什么:
constexpr uInt id = typeId<RectComponent>();
using Type = idType<id>::type;
您可以添加额外的括号以避免歧义:
using Type = idType<(typeId<RectComponent>())>::type;
这是有效的,因为(typeId<RectComponent>())
不是有效的函数声明。
当然operator uInt()
应该标constexpr
:
constexpr operator uInt() { return val; }
请参阅演示。
对于其他尝试这样做的人来说,值得一提的是,这个问题可以像这样完全避免:
template<typename T> class typeId_base {};
template<uInt id> class idType_base {};
template<uInt id>
using idType = typename idType_base<id>::type;
template<typename T>
inline constexpr uInt typeId = typeId_base<T>::val;
#define Generate_Type_To_ID_Mapping( id, t)
class t;
template<>class typeId_base<t> { public: static constexpr uInt val = id;};
template<>class idType_base<id> { public: using type = t; };
Generate_Type_To_ID_Mapping(0, Entity);
Generate_Type_To_ID_Mapping(1, RectComponent);
Generate_Type_To_ID_Mapping(2, ConstraintComponent);
Generate_Type_To_ID_Mapping(3, TextComponent);
这允许简单地编写更简单和统一的idType<1>
和typeId<RectComponent>
:
int main()
{
//from type to index
std::cout << typeid(TextComponent).name() << " has ID " << typeId<TextComponent> << std::endl;
//from index to type
std::cout << typeid(idType<1>).name() << " has ID " << typeId<RectComponent> << std::endl;
}
甚至typeId<idType<1>>
相关文章:
- C++转换参数初始化问题
- C2664 无法从'initializer list'转换参数
- 隐式可转换参数,但属于引用类型
- 传递到函数(C )时转换参数
- 了解错误 C2664:无法转换参数 1
- 错误 C2664:无法从'NvPhysicalGpuHandle'转换参数 1
- Unicode 字符问题/转换参数
- 在运行时根据某些元数据强制转换参数包值
- 错误 C2664:"errno_t wcstombs_s(size_t *,字符 *,size_t,常量 wchar_t *,size_t)":无法转换参数 4
- 错误C2664:无法转换参数错误
- 无法转换参数错误
- Boost.python自动转换参数
- "尝试升级使用已弃用的转换参数指定的输入文件"是什么意思?
- 是否可以在函数模板中转换参数C++?
- 错误C2664:无法转换参数(指纹传感器检测)
- 无法转换参数 - 模板错误
- 编译zxing时,Libconv无法转换参数
- C++ 无法转换参数
- std::p air<_Ty1,_Ty2>::p air<_Ty1,_Ty2>& 无法转换参数
- 无法转换参数-转换丢失限定符