c++ - 使用 using 定义的类型不能用作函数参数

标签 c++ templates c++17 using

在我的真实世界应用程序中,我使用 CRTP 来构造一个或多或少的大类“堆栈”。我需要知道这些类的“共同基础”是什么,所以我在“堆栈”的其中一个类中定义了一个 typeusing。后来我不想将这个定义的类型用作模板函数参数,但这行不通,我总是遇到“无法使用 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
}

关于c++ - 使用 using 定义的类型不能用作函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58433968/

相关文章:

c++ - 关于用括号括起来的声明类型是什么的问题

c++ - 将结构序列化/反序列化为二进制数据包

c++ - 为什么 puts() 函数没有在客户端 - 服务器套接字代码中打印多个输出?

c++ - AllocaInst 的使用示例 : LLVM

c++ - 推断可变模板参数包元素的类型

c++ - 关于 ODR 违规和模板变量

c++ - 如何在 C++ 中忽略动态链接库中的 main 方法

c++ - 模板类和主要

c++ - 为什么我们应该为 initializer_list 的情况重载转发构造函数?

c++ - 有没有办法在 C++17 中创建编译时类型映射以进行类型检查?