在编译时在模板中连接编译时字符串?

时间:2014-07-16 14:26:54

标签: c++ string templates c++11 template-meta-programming

目前我有:

template <typename T> struct typename_struct<T*> {
    static char const* name() { 
        return (std::string(typename_struct<T>::name()) + "*").c_str(); 
    }
};

我想知道是否可以避免在我被迫分配字符串来执行连接的整个位置。

这一切都发生在编译时,即我打算在引用"int****"时获取字符串typename_struct<int****>::name()。 (假设我已经为int声明了相应的特殊化,返回"int"

现在编写代码时,编译器是否仅在编译时使用std :: string进行串联? (我会好的)或者这样的调用会在运行时导致基于4 std :: string的连接吗? (我不会那么好)

3 个答案:

答案 0 :(得分:5)

你可以使用这样的东西。一切都在编译时发生。使用baseize_typename_struct来定义基本类型。

template <const char* str, int len, char... suffix>
struct append {
  static constexpr const char* value() {
    return append<str, len-1, str[len-1], suffix...>::value();
  }
};

template <const char* str, char... suffix>
struct append<str, 0, suffix...> {
  static const char value_str[];
  static constexpr const char* value() {
    return value_str;
  }
};

template <const char* str, char... suffix>
const char append<str, 0, suffix...>::value_str[] = { suffix..., 0 };


template <typename T>
struct base_typename_struct;

template <>
struct base_typename_struct<int> {
  static constexpr const char name[] = "int";    
};


template <typename T, char... suffix>
struct typename_struct {
  typedef base_typename_struct<T> base;
  static const char* name() {
    return append<base::name, sizeof(base::name)-1, suffix...>::value();
  }
};

template <typename T, char... suffix>
struct typename_struct<T*, suffix...>:
  public typename_struct<T, '*', suffix...> {
};


int main() {
  cout << typename_struct<int****>::name() << endl;
}

答案 1 :(得分:3)

不使用递归模板的替代方法:

Dim strSQL As String
Dim qdef As Querydef

' PREPARE SQL STATEMENT
strSQL = "PARAMETERS [MaxDateParam] Date, [FormIDParam] Long;" _
           & "UPDATE Tbl_Name SET CollectionDate = [MaxDateParam]" _
           & " WHERE PID = [FormIDParam];"

' BUILD TEMP QUERY
Set qdef = CurrentDb.CreateQueryDef("", strSQL)

' BIND PARAMETERS
qdef!MaxDateParam = DMax("Date1_Event", "TBL_Event", "ID=" & [Forms]![FRM_Main]![ID])
qdef!FormIDParam = [Forms]![FRM_Main]![ID]

' EXECUTE ACTION
qdef.Execute dbFailOnError

Set qdef = Nothing

示例:

#include <utility>
template<int...I> using is      = std::integer_sequence<int,I...>;
template<int N>   using make_is = std::make_integer_sequence<int,N>;

constexpr auto size(const char*s) { int i = 0; while(*s!=0){++i;++s} return i; }

template<const char*, typename, const char*, typename>
struct concat_impl;

template<const char* S1, int... I1, const char* S2, int... I2>
struct concat_impl<S1, is<I1...>, S2, is<I2...>> {
    static constexpr const char value[]
    {
        S1[I1]..., S2[I2]..., 0
    };
};

template<const char* S1, const char* S2>
constexpr auto concat {
    concat_impl<S1, make_is<size(S1)>, S2, make_is<size(S2)>>::value
};
通过将第二个constexpr const char a[] = "int"; constexpr const char c[] = "**"; #include <iostream> int main() { std::cout << concat<a,b> << '\n'; } 参数替换为append

const char*个字符串也可以像这样实现。

答案 2 :(得分:0)

我不确定你在搜索什么,但我相信你对typeid和name-demangling(你使用哪个编译器?)的组合感兴趣。

在gcc中它会像

#include<iostream>
#include <string>
#include <typeinfo>
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
using namespace std;

std::string demangle(const char* name) {
    int status = -4; // some arbitrary value to eliminate the compiler warning

    // enable c++11 by passing the flag -std=c++11 to g++
    std::unique_ptr<char, void(*)(void*)> res {
        abi::__cxa_demangle(name, NULL, NULL, &status),
        std::free
    };
    return (status==0) ? res.get() : name ;
}

template <typename T> struct typename_struct {
  static std::string name() {
    std::string typeName = typeid(T).name();
    return demangle(typeName.c_str());
  }
};

int main(){

  cout << typename_struct<int****>::name(); // Prints "int****"

  return 0;
}

http://ideone.com/nLsFF0

资料来源:https://stackoverflow.com/a/4541470/1938163

至于你的问题:那些不是constexpr构造,因此评估在运行时发生,尽管模板化的参数和代码在编译时被实例化。

使用模板并不意味着其中包含的每条指令都将在“编译时”执行和解析。

我相信你无法在编译时实现这一系列的东西,因为涉及到了de-mangling函数(特定于ABI)。如果我将您的问题解释错误,请告诉我。