特质实现给出了Clang和G 的不同结果,这是正确的
Trait implementation gives different results with clang and g++, which is right?
我开始慢慢填补我对C 模板的知识差距,并且在阅读了很多有关如何处理错误之前,在编译器真正进入模板代码的主体之前,我出现了使用以下结构来检查对象是否提供了我需要的接口。
在模型类中可见所需的接口。
#include <iostream>
#include <type_traits>
template <typename T>
struct is_model {
private:
template <typename B, typename A> struct size_t_allowed;
template <typename B> struct size_t_allowed<B, size_t>{};
template <typename B, typename A> struct double_allowed;
template <typename B> struct double_allowed<B, double>{};
template <typename Z> static auto test(const Z* z) -> decltype(
size_t_allowed<size_t,decltype(z->getS())>(),
size_t_allowed<size_t,decltype(z->getA())>(),
double_allowed<double,decltype(z->getTransitionProbability(0,0,0))>(),
double_allowed<double,decltype(z->getExpectedReward(0,0,0))>(),
std::true_type{} );
template <typename> static auto test(...) -> std::false_type;
public:
enum { value = std::is_same<decltype(test<T>(0)), std::true_type>::value };
};
struct Model {
size_t getS() const { return 0;}
size_t getA() const { return 0;}
double getTransitionProbability(size_t, size_t, size_t) const {return 0.0;}
double getExpectedReward(size_t, size_t, size_t) const {return 0.0;}
};
template <typename M>
void algorithm(M, typename std::enable_if<is_model<M>::value>::type * = nullptr) {
std::cout << "Algorithm has been performed.n";
}
int main() {
std::cout << is_model<int>::value << "n";
std::cout << (is_model<Model>::value ? "Yes" : "No" ) << "n";
Model m;
algorithm(m);
return 0;
}
我的问题如下:
- G 4.8.1正确编译了代码,并打印所有消息。clang 3.4实际上不会返回
is_model<Model>::value
的false,并且无法编译algorithm(m)
。哪个是对的? - 目前,我只找到了检查接口返回类型的(不良)方式。有可能使事情变得更好吗?我无法为结构
*_allowed
使用一个模板参数,因为否则编译器会在类范围内抱怨专用结构。 - 最后,我想知道如何对函数的参数进行检查,以及是否有意义。
编辑:多亏了Jarod的答案,我提高了解决方案。由于我喜欢它的清洁度,所以我仍然将所有内容都放入一个课程。此外,我发现了Clang的问题:由于某种原因,在这种情况下,它无法正确解析std::true_type{}
,而std::declval<std::true_type>()
也无法使用。用std::true_type()
代替它。仍然没有任何线索,我什至试图重新安装整个过程。
template <typename T>
struct is_model {
private:
template<typename U, U> struct helper{};
template <typename Z> static auto test(Z* z) -> decltype(
helper<size_t (Z::*)() const, &Z::getS>(),
helper<size_t (Z::*)() const, &Z::getA>(),
helper<double (Z::*)(size_t,size_t,size_t) const, &Z::getTransitionProbability>(),
helper<double (Z::*)(size_t,size_t,size_t) const, &Z::getExpectedReward>(),
std::true_type());
template <typename> static auto test(...) -> std::false_type;
public:
enum { value = std::is_same<decltype(test<T>((T*)nullptr)),std::true_type>::value };
};
以下可能会有所帮助,它检查完整的签名:
#include <cstdint>
#include <type_traits>
#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature)
template <typename U>
class traitsName
{
private:
template<typename T, T> struct helper;
template<typename T>
static std::uint8_t check(helper<signature, &funcName>*);
template<typename T> static std::uint16_t check(...);
public:
static
constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t);
}
DEFINE_HAS_SIGNATURE(has_getS, T::getS, size_t (T::*)() const);
DEFINE_HAS_SIGNATURE(has_getA, T::getA, size_t (T::*)() const);
DEFINE_HAS_SIGNATURE(has_getTransitionProbability, T::getTransitionProbability, double (T::*)(size_t, size_t, size_t) const);
DEFINE_HAS_SIGNATURE(has_getExpectedReward, T::getExpectedReward, double (T::*)(size_t, size_t, size_t) const);
template <typename T>
struct is_model :
std::conditional<has_getS<T>::value
&& has_getA<T>::value
&& has_getTransitionProbability<T>::value
&& has_getExpectedReward<T>::value,
std::true_type, std::false_type>::type
{};
测试它:
struct Model {
size_t getS() const { return 0;}
size_t getA() const { return 0;}
double getTransitionProbability(size_t, size_t, size_t) const {return 0.0;}
double getExpectedReward(size_t, size_t, size_t) const {return 0.0;}
};
static_assert(is_model<Model>::value, "it should respect contract");
static_assert(!is_model<int>::value, "it shouldn't respect contract");
相关文章:
- 为什么 MSVC _count_of实现将 0 添加到 sizeof 的结果中?
- OpenCV 混合模式实现:为什么看似等效的操作会产生不同的结果?
- libc++ 对 std::map/set::equal_range 的实现给出了意想不到的结果
- 微小加密算法实现会产生意想不到的结果
- 为什么在 C++ 中实现高斯勒让德算法没有产生结果
- 反向 Cuthill-McKee 算法:在 Matlab 和提升实现中具有无与伦比的结果
- 在我的C++链表实现中取消引用节点指针,给出意想不到的结果
- 在不同的平台/编译器上实现相同的浮点计算结果
- 为什么定义了sizeof实现的结果
- 特质实现给出了Clang和G 的不同结果,这是正确的
- C void*任何类型实现都会返回奇怪的结果
- Negamax C++实现给出了错误的结果
- 着色器中实现双精度cos()的结果是NaN,但在CPU上运行良好.出了什么问题
- C++,Lapack-Cholesky分解实现结果不准确
- 如何在c++中实现此结果?指向数组的数组
- 实现多个返回语句 c++ 时出现奇怪的结果
- 绕过虚拟模板功能以实现期望的结果
- C++成员函数结果缓存实现
- C++中合并排序实现的特殊行为,排序后的结果不应该在适当的位置
- HashTable实现的错误结果