2013-07-18 2 views
7

나는 다음 (아래 코드의 관련 부분을) 할 노력하고있어 :컴파일 타임 동안 constexpr 문자열을 인쇄하는 방법이 있습니까?

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

답변

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; 
} 

전문화에 내가 true_t하지 별칭 또는 std::true_type의 동등한 것으로 추정하지만, 단지 아니라 _check_concept::struct run<true_t> 컨테이너 유형이 인 일부 수신자는 ResultType입니다. 테스트 프로그램에 표시된 은 IsContainerCheck<ResultType>()static_assert 일 때 에 ResultType에 따라 달라지기 때문에 특별한 지정이 필요하지 않습니다. 특수하지 않은 run<ResultType>::apply()입니다.

+0

필자는 템플릿이 인스턴스화 되 자마자 검사가 수행되기를 기대합니다. 이는 반드시 개체가 생성 될 필요는 없습니다. – aschepler

+0

그렇습니다. 그냥 시도하고 표현하기 위해 편집했습니다. –

+0

나는 단지 그 파라를 긁을 것이다.래퍼에서 생성자 호출을 필요로하는 문제가 있다고 생각했지만 간단하게 만들 수는 없으므로 코드에 문제가있을 수 있습니다. –

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(); 

이 솔루션은 아마 가장 우아한 아니다 그러나 나는이 짧은 어설 메시지 유지 :

In file included from ../main.cpp:4:0: ../constraint.check.hpp: In instantiation of ‘static constexpr int IsContainerCheck::printError() [with BoolType = std::integral_constant; ContainerType = float]’: ../constraint.check.hpp:61:34: required from ‘static constexpr int check_concept::apply() [with ConceptCheck = IsContainerCheck; ModelTypes = {std::vector >, std::vector >, float, int}]’ ../main.cpp:25:83: required from here ../constraint.check.hpp:74:3: error: static assertion failed: Type is not a container model static_assert(BoolType::value, "Type is not a container model");

를이 내가 생각 해낸 것입니다

assert는 check_concept 템플릿 전문화가 완료된 후 constexpr 메소드에서 발행됩니다. 정적 어서 트를 템플릿 클래스 정의에 직접 포함 시키면 전체 check_concept_impl 재귀 스택을 오류 메시지로 끌어다 놓을 수 있습니다. 각 재귀 eval_if 호출이 emended되어 볼 수 있듯이

template<typename ContainerType> 
struct IsContainerCheck 
{ 
static_assert(is_container<ContainerType>::type::value, "Type is not a container model"); 
}; 

오류

../constraint.check.hpp: In instantiation of ‘struct IsContainerCheck’: ../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl’ /usr/include/boost/mpl/eval_if.hpp:38:31: required from ‘struct boost::mpl::eval_if, _details::check_concept_impl, boost::mpl::identity > > >’ ../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl >, float, int>’ /usr/include/boost/mpl/eval_if.hpp:38:31: required from ‘struct boost::mpl::eval_if, _details::check_concept_impl >, float, int>, boost::mpl::identity > > >’ ../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl >, std::vector >, float, int>’ ../constraint.check.hpp:53:84: required from ‘struct check_concept >, std::vector >, float, int>’ ../main.cpp:25:81: required from here ../constraint.check.hpp:72:2: error: static assertion failed: Type is not a container model static_assert(is_container::type::value, "Type is not a container model");

를 얻을 것이다 :

그래서 (일기 좋게 생략 변화의 나머지)처럼 뭔가에 IsContainerCheck 형질 변경 오류 메시지가 템플리트 매개 변수의 양과 유형에 종속적이 G로 오류 설명에 좋지 않습니다.

관련 문제