C++ 使用定义的类型不能用作函数参数
在我的实际应用程序中,我使用CRTP构造了一个或多或少的大类堆栈。我需要知道这些类的公共基是什么,所以我在堆栈的一个类中定义了一个类型。稍后我不想使用这个定义的类型作为模板函数参数,但这不起作用,我总是遇到无法用g++推断模板参数“VAR_type” 是否有机会修复该问题,因为不建议手动定义类型,因为如果类堆栈的结构将发生更改,则应该自动更改类型C++ 使用定义的类型不能用作函数参数,c++,templates,c++17,using,C++,Templates,C++17,Using,在我的实际应用程序中,我使用CRTP构造了一个或多或少的大类堆栈。我需要知道这些类的公共基是什么,所以我在堆栈的一个类中定义了一个类型。稍后我不想使用这个定义的类型作为模板函数参数,但这不起作用,我总是遇到无法用g++推断模板参数“VAR_type” 是否有机会修复该问题,因为不建议手动定义类型,因为如果类堆栈的结构将发生更改,则应该自动更改类型 template < typename T> struct B { using HERE = B<T>; }; templat
template < typename T> struct B { using HERE = B<T>; };
template < typename T> struct C: public B<T> { };
template <typename T>
using COMMON_BASE = typename C<T>::HERE;
template < typename T>
void Print2( )
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
// g++ reports:
// error: no matching function for call to 'CheckMe(COMMON_BASE<int>*&)'
// note: candidate: 'template<class VAR_TYPE> void CheckMe(COMMON_BASE<VAR_TYPE>*)'
// note: template argument deduction/substitution failed:
// note: couldn't deduce template parameter 'VAR_TYPE'
template < typename VAR_TYPE >
void CheckMe( COMMON_BASE<VAR_TYPE>* ) { std::cout << "COMMON_BASE<>" << std::endl; }
// "hardcoded" works fine but should be avoided
//template < typename VAR_TYPE >
//void CheckMe( B<VAR_TYPE>* ) { std::cout << "B<>" << std::endl; }
void CheckMe( int* ) { std::cout << "int" << std::endl; }
//void CheckMe( ... ){ std::cout << "default" << std::endl; }
int main()
{
COMMON_BASE< int >* cb;
B<int>* bi;
CheckMe( cb );
CheckMe( bi );
Print2< COMMON_BASE<int>* >(); // gives: void Print2() [with T = B<int>*]
}
不幸的是,模板参数推导只在直接上下文中起作用,否则做是不合逻辑的。想想这个例子:
template<typename T>
using common_base = std::conditional<(sizeof(T) > 8), int, float>
template<typename T>
void call_me(common_base<T>) {
// ...
}
int main() {
call_me(1.4f); // What is T?
}
这看起来很明显,但这也是你的例子所发生的事情。你可以想象:
// Ah! Fooled you compiler!
template<> struct B<int> { using HERE = B<std::string>; };
那么在那之后,这些调用应该推断出什么呢
CheckMe(bi); // should deduce B<int> or B<std::string>?
正如您所看到的,编译器无法通过非即时上下文进行推断,因为可能不存在1:1的关系,有时它就是无法进行推断
那你该怎么办
简化模板函数是使其正常工作的常用方法:
template<typename T>
struct B {
using HERE = B<T>;
using type = T;
};
template<typename BaseType>
void CheckMe(BaseType* bt) {
using VAR_TYPE = BaseType::type; // yay, can use member type
}
但是,如果我必须使用重载来选择被调用的函数,我不能首先进入它。所以我不得不考虑一个不同的设计。。。不好的事情,但现实:-重载对这样的模板也很有效。。。除非我弄错了什么?你说的第一步是什么意思?像调试器中的第一步之类的吗?我的示例显示重载,它不适用于从另一个模板内部使用获取类型。所以我不能继续使用这种方法,因为我需要重载和在某处定义的类型。一般来说,重载与模板一起工作是非常清楚的;