我已经基于this question创建了一个概念检查类,其目的是确保给定的类具有名为baseUnitConversionFactor
的静态成员函数。该类使用msvc2013编译并正常工作,但它不能在gcc 4.9.2(使用-std = c ++ 14)上编译并出现错误:
错误:'{anonymous} :: UnitsTest_conceptChecker_Test :: TestBody():: validUnit :: baseUnitConversionFactor' 不是类型'double(*)()'的有效模板参数,因为 'static double {anonymous} :: UnitsTest_conceptChecker_Test :: TestBody():: validUnit :: baseUnitConversionFactor()' 没有联系
static std :: true_type test(tester<& U :: baseUnitConversionFactor> *);
我真的不知道这意味着什么,而且更熟悉在视觉工作室中编写模板(显然)更为谨慎的环境。任何人都可以帮助弄清楚我需要做些什么来解决这个问题?
概念检查器类
template <typename T>
struct has_baseUnitConversionFactor
{
template<double(*)()> struct tester;
template<typename U>
static std::true_type test(tester<&U::baseUnitConversionFactor>*);
template<typename U>
static std::false_type test(...);
static const bool value = decltype(test<T>(0))::value;
};
测试我认为会导致错误
TEST_F(UnitsTest, conceptChecker)
{
struct validUnit
{
static inline double baseUnitConversionFactor() { return 0.0; }
typedef void unit_category;
typedef void base_unit_type;
};
EXPECT_TRUE(has_baseUnitConversionFactor<validUnit>::value);
}
答案 0 :(得分:2)
在C ++ 11和C ++ 14中,指针/引用模板参数必须引用具有链接的实体(在C ++ 03中,它们仅限于具有外部链接的实体)。本地类没有链接,它的成员函数也没有。
此限制已在{+ 3}}中在C ++ 17中删除,而GCC主干声称已实施该论文,但显然不是链接部分。
避免此问题的步骤不需要使用&U::baseUnitConversionFactor
作为模板非类型参数。令人高兴的是,测试表达式T::baseUnitConversionFactor()
有效且准确返回double
的更简单方法是:
template <typename T, class=double>
struct has_baseUnitConversionFactor : std::false_type { };
template <typename T>
struct has_baseUnitConversionFactor<T, decltype(T::baseUnitConversionFactor())>
: std::true_type { };
这取决于表达式SFINAE(但原来也是如此),所以我不确定它是否适用于MSVC 2013.
要进行更一般的检查,您可能需要查看N4268。该cppreference页面有一个参考实现。
答案 1 :(得分:0)
令人讨厌的是,这个问题似乎是由gtest使用匿名命名空间的方式引起的。将validUnit
声明移动到测试夹具(称为UnitsTest)并更改EXPECT语句以使用fixture命名空间解决了这个问题。
更新了灯具
class UnitsTest : public ::testing::Test {
protected:
UnitsTest()
{
}
virtual ~UnitsTest()
{
}
virtual void SetUp()
{
}
virtual void TearDown()
{
}
struct validUnit
{
static inline double baseUnitConversionFactor() { return 0.0; }
typedef void unit_category;
typedef void base_unit_type;
};
};
更新测试
TEST_F(UnitsTest, conceptChecker)
{
EXPECT_TRUE(has_baseUnitConversionFactor<UnitsTest::validUnit>::value);
}