2013-07-18 35 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; 
} 

在您的專業_check_concept::struct run<true_t>我假定 true_t別名或std::true_type等同,而是 剛一些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");

在check_concept模板專門化完成之後,斷言在constexpr方法中發佈。直接將靜態斷言嵌入到模板類定義中會將整個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: 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");

正如你可以看到每個遞歸eval_if呼叫仔細的校勘在錯誤描述中是不好的,因爲它使得錯誤信息與模板參數的數量和類型有關。

相關問題