我正在尝试执行以下操作(仅下面的相关代码部分):
template<typename ContainerType>
struct IsContainerCheck : is_container<ContainerType>
{
static constexpr char* err_value = "Type is not a container model";
};
namespace _check_concept {
template<typename ResultType>
struct run {
constexpr static int apply() {
static_assert(false, IsContainerCheck<ResultType>::err_value)
return 0;
}
};
template<>
struct run<true_t> {
constexpr static int apply() {
return 0;
}
};
}
这会失败,因为static_assert只允许打印文字。与BOOST_STATIC_ASSERT_MSG宏相同。
所以我的问题是 - 在编译期间有没有办法输出constexpr字符串? 如果有一个gcc扩展提供这个功能也很棒。
使用的编译器gcc 4.8.1
答案 0 :(得分:6)
GCC没有提供您想要的机制。但是你不需要 如果你能够在某种程度上重构你的代码,如图所示 以下计划。 (我填补了一些空白,以便给我们一个 可编辑的例子):
#include <type_traits>
#include <vector>
template<typename ContainerType>
struct is_container
{
static bool const value = false;
};
template<>
struct is_container<std::vector<int>>
{
static bool const value = true;
};
template<typename ContainerType>
struct IsContainerCheck // : is_container<ContainerType> <- Uneccessary
{
static_assert(is_container<ContainerType>::value,
"Type is not a container model");
};
namespace _check_concept {
template<typename ResultType>
struct run {
constexpr static int apply() {
return (IsContainerCheck<ResultType>(),0);
}
};
// No such specialization is necessary. Delete it.
// template<>
// struct run<true_t> {
// constexpr static int apply() {
// return 0;
// }
//};
}
using namespace _check_concept;
int main(int argc, char **argv)
{
auto verdict0 = run<std::vector<int>>::apply();
(void)verdict0;
// The following line will static_assert: "Type is not a container model"
auto verdict1 = run<float>::apply();
(void)verdict1;
return 0;
}
在你的专业化_check_concept::struct run<true_t>
中,我认为
true_t
不是别名或等同于std::true_type
,而是。{
只是某些ResultType
的占位符,它是一种容器类型。如
测试程序显示,现在不需要这样的专业化,因为
IsContainerCheck<ResultType>()
将static_assert
取决于ResultType
run<ResultType>::apply()
上的非专业{{1}}。
答案 1 :(得分:0)
我有一些时间(和一个好的利口酒一起来)来思考这个问题。这就是我想出的:
namespace _details {
struct PassedCheck {
constexpr static int printError () {
return 0; //no error concept check passed
}
};
template<template<typename> class ConceptCheck, typename ...ModelTypes>
struct check_concept_impl;
template<template<typename> class ConceptCheck, typename FirstType, typename ...ModelTypes>
struct check_concept_impl<ConceptCheck, FirstType, ModelTypes...> : mpl::eval_if< typename ConceptCheck<FirstType>::type,
check_concept_impl<ConceptCheck, ModelTypes...>,
mpl::identity<ConceptCheck<FirstType>>>
{ };
template<template<typename> class ConceptCheck, typename LastType>
struct check_concept_impl<ConceptCheck, LastType> : mpl::eval_if<typename ConceptCheck<LastType>::type,
mpl::identity<PassedCheck>,
mpl::identity<ConceptCheck<LastType>>>
{ };
}
template<template<typename> class ConceptCheck, typename ...ModelTypes>
struct check_concept {
private:
typedef typename _details::check_concept_impl<ConceptCheck, ModelTypes...>::type result_type;
public:
// the constexpr method assert produces shorter, fixed depth (2) error messages than a nesting assert in the trait solution
// the error message is not trahsed with the stack of variadic template recursion
constexpr static int apply() {
return result_type::printError();
}
};
template<typename ContainerType>
struct IsContainerCheck : is_container<ContainerType>
{
template<typename BoolType = false_t>
constexpr static int printError () {
static_assert(BoolType::value, "Type is not a container model");
return 0;
}
};
和用法:
check_concept<IsContainerCheck, std::vector<int>, std::vector<int>, float, int>::apply();
解决方案可能不是最优雅的解决方案,但我保持断言信息简短:
在../main.cpp:4:0中包含的文件中: ../constraint.check.hpp:实例化'static constexpr int IsContainerCheck :: printError()[with BoolType = std :: integral_constant; ContainerType = float]': ../constraint.check.hpp:61:34:需要来自'static constexpr int check_concept :: apply()[with ConceptCheck = IsContainerCheck; ModelTypes = {std :: vector&gt;,std :: vector&gt;,float,int}]' ../main.cpp:25:83:从这里要求 ../constraint.check.hpp:74:3:错误:静态断言失败:类型不是容器模型 static_assert(BoolType :: value,“Type不是容器模型”);
在check_concept模板专门化完成后,在constexpr方法中发出assert。将静态断言直接嵌入到模板类定义中会将整个check_concept_impl递归堆栈拖到错误消息中。
因此将IsContainerCheck特性更改为类似的内容(为了可读性而省略了其余的更改):
template<typename ContainerType>
struct IsContainerCheck
{
static_assert(is_container<ContainerType>::type::value, "Type is not a container model");
};
会产生错误
../ constraint.check.hpp:在'struct IsContainerCheck'的实例化中: ../constraint.check.hpp:36:9:'struct _details :: check_concept_impl'需要 /usr/include/boost/mpl/eval_if.hpp:38:31:需要'struct boost :: mpl :: eval_if,_details :: check_concept_impl,boost :: mpl :: identity&gt; &GT; &GT;” ../constraint.check.hpp:36:9:需要'struct _details :: check_concept_impl&gt;,float,int&gt;' /usr/include/boost/mpl/eval_if.hpp:38:31:需要'struct boost :: mpl :: eval_if,_details :: check_concept_impl&gt;,float,int&gt ;, boost :: mpl :: identity&gt; &GT; &GT;” ../constraint.check.hpp:36:9:需要'struct _details :: check_concept_impl&gt;,std :: vector&gt;,float,int&gt;' ../constraint.check.hpp:53:84:需要'struct check_concept&gt;,std :: vector&gt;,float,int&gt;' ../main.cpp:25:81:从这里要求 ../constraint.check.hpp:72:2:错误:静态断言失败:类型不是容器模型 static_assert(is_container :: type :: value,“Type不是容器模型”);
正如您所看到的,每个递归eval_if调用都在错误描述中被修改,这是错误的,因为它使错误消息依赖于模板参数的数量和类型。