模板参数未满足所有要求
Templates arguments not fulfulling all requirements
这是可能的:
struct A {
//void f(); < not declared in struct A
};
template<typename T>
struct Wrapper {
T t;
void call_f() { t.f(); }
};
int main() {
Wrapper<A> w;
}
只要不调用w.call_f()
,这个编译就很好。由于A::f
不存在,因此无法实例化w.call_f()
。
我遇到了这样一个包装器模板的情况,它与不同的T
类型一起使用,这些类型并不总是实现接口的所有部分。(主要是为了避免代码重复(。
这不起作用:
struct A {
//using i_type = int; < not declared/defined
};
template<typename T>
struct Wrapper {
using its_i_type = typename T::i_type;
// compile error, even if `i_type` gets never used
};
int main() {
Wrapper<A> w;
}
这也不行:
struct A {
//using i_type = int; < not declared/defined
};
template<typename T>
struct Wrapper {
typename T::i_type call_f() { return 0; }
// does not compile, even if `call_f()` is never instantiated
};
int main() {
Wrapper<A> w;
}
有没有一种好的方法来处理这些情况,而不需要大量的代码重复(比如Wrapper
的专业化等(?
您可以推迟its_i_type
的类型推导。基本上,您创建了一个必须经过的简单包装器。
为了将其扩展到您需要的其他类型,(我想推荐类似type_traits
的解决方案,但由于您不想要专业化(您可以定义您需要的所有类型:
template<typename T>
struct Wrapper {
private:
template<typename U> struct i_typper { using type = typename U::i_type; };
template<typename U> struct k_typper { using type = typename U::k_type; };
template<typename U> struct p_typper { using type = typename U::p_type; };
public:
using i_trait = i_typper<T>;
using k_trait = k_typper<T>;
using p_trait = p_typper<T>;
};
示例:
struct A { using i_type = int; };
struct B { using i_type = int; using k_type = float; };
int main() {
Wrapper<A> w; //Works now.
Wrapper<A>::i_trait::type mk1; //Works
Wrapper<A>::k_trait::type mk2; //Fails, not defined
Wrapper<B>::i_trait::type mk3; //Works
Wrapper<B>::k_trait::type mk4; //Works
}
对于以下情况:
template<typename T>
struct Wrapper {
typename T::i_type call_f() { return 0; }
// does not compile, even if `call_f()` is never instantiated
};
这里有几个选项:
- 使该函数成为成员函数模板
- 使用某种形式的
type_traits
机制,该机制仍将涉及专业化 - 采用抽象基类
WrapperBase
中常见的Wrapper
内容的方法
对于第一个选项,您必须对其进行一点修改,以进一步推迟扣除
template<typename T>
struct Wrapper {
private:
template<typename U, typename> struct i_typper { using type = typename U::i_type; };
template<typename U, typename> struct k_typper { using type = typename U::k_type; };
template<typename U, typename> struct p_typper { using type = typename U::p_type; };
public:
using i_trait = i_typper<T, void>;
using k_trait = k_typper<T, void>;
using p_trait = p_typper<T, void>;
template<typename U = void>
typename k_typper<T, U>::type call_f() { return 0; }
};
我将把第二个选项作为练习:(它可能最终会变成:
template<typename T>
struct wrapper_traits {
....
};
template<>
struct wrapper_traits<A>{
using ....
};
template<typename T>
struct Wrapper {
....
public:
using i_trait = wrapper_traits<T>;
using k_trait = wrapper_traits<T>;
using p_trait = wrapper_traits<T>;
};
贾罗德的答案更简单。但如果您没有访问std::experimental
的权限,或者您的公司代码政策禁止您。。。
使用std::experimental::is_detected
,您可以进行
template<typename T>
using i_type_t = typename T::i_type;
template<typename T>
struct Wrapper {
using its_i_type = typename std::experimental::detected_t<i_type_t, T>;
// would be T::i_type or std::experimental::nonesuch
};
或者为了更好地处理案件,比如:
template<typename T, bool = std::experimental::is_detected<i_type_t, T>::value>
struct WrapperWithIType {
// Empty for false case.
};
template<typename T>
struct WrapperWithIType<T, true> {
using its_i_type = i_type_t<T>;
its_i_type call_f() { return 0; }
};
然后
template<typename T>
struct Wrapper : WrapperWithIType<T> {
// Common stuff
};
相关文章:
- 将代码移出类定义时未扩展参数包
- 在未满足条件时的任何时刻结束一个段循环
- 如何知道创建对象时是否未传入参数?
- argv[] 未注册参数
- 具有未定义参数的私有副本构造函数
- 在 excel 中使用 C++ dll 时未考虑参数
- JNI 在具有 x86javapath 的 x64 计算机上的 x86java 上出现未满足的链接错误
- 未满足的依赖项:xscrnsaver
- C++:未使用参数优化的力度
- 用于未使用参数参考的单线解决方案
- 传递 C++11 中具有未指定参数的函数
- 未打包参数的类型
- 如果未传递参数,则使用默认值
- OpenCV CommandLineParser未指定参数
- 如果未满足某些条件,从方法返回什么?
- 函数包含未命名参数
- 编译器会根据我处理未引用参数的方式做不同的事情吗
- 可移植的未使用参数宏用于C和c++的函数签名
- 模板参数未满足所有要求
- 函数的未命名参数是否可以具有默认值