Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用定义的类型不能用作函数参数_C++_Templates_C++17_Using - Fatal编程技术网

C++ 使用定义的类型不能用作函数参数

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

在我的实际应用程序中,我使用CRTP构造了一个或多或少的大类堆栈。我需要知道这些类的公共基是什么,所以我在堆栈的一个类中定义了一个类型。稍后我不想使用这个定义的类型作为模板函数参数,但这不起作用,我总是遇到无法用g++推断模板参数“VAR_type”

是否有机会修复该问题,因为不建议手动定义类型,因为如果类堆栈的结构将发生更改,则应该自动更改类型

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
}

但是,如果我必须使用重载来选择被调用的函数,我不能首先进入它。所以我不得不考虑一个不同的设计。。。不好的事情,但现实:-重载对这样的模板也很有效。。。除非我弄错了什么?你说的第一步是什么意思?像调试器中的第一步之类的吗?我的示例显示重载,它不适用于从另一个模板内部使用获取类型。所以我不能继续使用这种方法,因为我需要重载和在某处定义的类型。一般来说,重载与模板一起工作是非常清楚的;