From 3cfb22e94ea9ccaf5ed9221fe82221a8fff0bc5d Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Thu, 13 Apr 2017 15:43:19 +0200 Subject: [PATCH 1/2] Add explicit visibility for class and function templates (refs #27) --- cmake/Custom.cmake | 13 +++++++++ source/baselib/CMakeLists.txt | 11 ++++++-- source/codegeneration/template_api.h.in | 23 ++++++++++++++++ source/codegeneration/template_msvc_api.in | 23 ++++++++++++++++ source/examples/fibcmd/main.cpp | 4 ++- source/fiblib/CMakeLists.txt | 13 +++++++-- source/fiblib/include/fiblib/CTFibonacci.h | 29 ++++++++++++++++++++ source/fiblib/include/fiblib/CTFibonacci.inl | 28 +++++++++++++++++++ 8 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 source/codegeneration/template_api.h.in create mode 100644 source/codegeneration/template_msvc_api.in create mode 100644 source/fiblib/include/fiblib/CTFibonacci.h create mode 100644 source/fiblib/include/fiblib/CTFibonacci.inl diff --git a/cmake/Custom.cmake b/cmake/Custom.cmake index e0e690f..4e44820 100644 --- a/cmake/Custom.cmake +++ b/cmake/Custom.cmake @@ -44,3 +44,16 @@ function(list_extract OUTPUT REGEX) set(${OUTPUT} ${${OUTPUT}} PARENT_SCOPE) endfunction(list_extract) + + +# Creates an export header similar to generate_export_header, but for templates. +# The main difference is that for MSVC, templates must not get exported. +# When the file ${export_file} is included in source code, the macro ${target_id}_TEMPLATE_API +# may get used to define public visibility for templates on GCC and Clang platforms. +function(generate_template_export_header target target_id export_file) + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC") + configure_file(${PROJECT_SOURCE_DIR}/source/codegeneration/template_msvc_api.h.in ${CMAKE_CURRENT_BINARY_DIR}/${export_file}) + else() + configure_file(${PROJECT_SOURCE_DIR}/source/codegeneration/template_api.h.in ${CMAKE_CURRENT_BINARY_DIR}/${export_file}) + endif() +endfunction() diff --git a/source/baselib/CMakeLists.txt b/source/baselib/CMakeLists.txt index 59655cc..806eac2 100644 --- a/source/baselib/CMakeLists.txt +++ b/source/baselib/CMakeLists.txt @@ -19,9 +19,10 @@ message(STATUS "Lib ${target}") # Set API export file and macro string(MAKE_C_IDENTIFIER ${target} target_id) string(TOUPPER ${target_id} target_id) -set(feature_file "include/${target}/${target}_features.h") -set(export_file "include/${target}/${target}_api.h") -set(export_macro "${target_id}_API") +set(feature_file "include/${target}/${target}_features.h") +set(export_file "include/${target}/${target}_export.h") +set(template_export_file "include/${target}/${target}_api.h") +set(export_macro "${target_id}_API") # @@ -90,6 +91,10 @@ generate_export_header(${target} EXPORT_FILE_NAME ${export_file} EXPORT_MACRO_NAME ${export_macro} ) +generate_template_export_header(${target} + ${target_id} + ${template_export_file} +) # diff --git a/source/codegeneration/template_api.h.in b/source/codegeneration/template_api.h.in new file mode 100644 index 0000000..1564245 --- /dev/null +++ b/source/codegeneration/template_api.h.in @@ -0,0 +1,23 @@ + +#ifndef ${target_id}_TEMPLATE_API_H +#define ${target_id}_TEMPLATE_API_H + +#include <${target}/${target}_export.h> + +#ifdef ${target_id}_STATIC_DEFINE +# define ${target_id}_TEMPLATE_API +# define ${target_id}_TEMPLATE_NO_EXPORT +#else +# ifndef ${target_id}_TEMPLATE_API +# ifdef ${target}_EXPORTS + /* We are building this library */ +# define ${target_id}_TEMPLATE_API __attribute__((visibility("default"))) +# else + /* We are using this library */ +# define ${target_id}_TEMPLATE_API __attribute__((visibility("default"))) +# endif +# endif + +#endif + +#endif diff --git a/source/codegeneration/template_msvc_api.in b/source/codegeneration/template_msvc_api.in new file mode 100644 index 0000000..834dfda --- /dev/null +++ b/source/codegeneration/template_msvc_api.in @@ -0,0 +1,23 @@ + +#ifndef ${target_id}_TEMPLATE_API_H +#define ${target_id}_TEMPLATE_API_H + +#include <${target}/${target}_export.h> + +#ifdef ${target_id}_STATIC_DEFINE +# define ${target_id}_TEMPLATE_API +# define ${target_id}_TEMPLATE_NO_EXPORT +#else +# ifndef ${target_id}_TEMPLATE_API +# ifdef ${target}_EXPORTS + /* We are building this library */ +# define ${target_id}_TEMPLATE_API +# else + /* We are using this library */ +# define ${target_id}_TEMPLATE_API +# endif +# endif + +#endif + +#endif diff --git a/source/examples/fibcmd/main.cpp b/source/examples/fibcmd/main.cpp index b7c50cd..30d9829 100644 --- a/source/examples/fibcmd/main.cpp +++ b/source/examples/fibcmd/main.cpp @@ -3,6 +3,7 @@ #include +#include #include @@ -15,7 +16,8 @@ int main(int /*argc*/, char* /*argv*/[]) // Calculate and print fibonacci number std::cout << "Fibonacci library" << std::endl; std::cout << "========================================" << std::endl; - std::cout << "Fibonacci(8) = " << fiblib::Fibonacci()(8) << std::endl; + std::cout << "CTFibonacci(6) = " << fiblib::CTFibonacci<6>::value << std::endl; + std::cout << "Fibonacci(8) = " << fiblib::Fibonacci()(8) << std::endl; std::cout << std::endl; return 0; diff --git a/source/fiblib/CMakeLists.txt b/source/fiblib/CMakeLists.txt index 8efb3fa..cbc2735 100644 --- a/source/fiblib/CMakeLists.txt +++ b/source/fiblib/CMakeLists.txt @@ -19,9 +19,10 @@ message(STATUS "Lib ${target}") # Set API export file and macro string(MAKE_C_IDENTIFIER ${target} target_id) string(TOUPPER ${target_id} target_id) -set(feature_file "include/${target}/${target}_features.h") -set(export_file "include/${target}/${target}_api.h") -set(export_macro "${target_id}_API") +set(feature_file "include/${target}/${target}_features.h") +set(export_file "include/${target}/${target}_export.h") +set(template_export_file "include/${target}/${target}_api.h") +set(export_macro "${target_id}_API") # @@ -32,6 +33,8 @@ set(include_path "${CMAKE_CURRENT_SOURCE_DIR}/include/${target}") set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/source") set(headers + ${include_path}/CTFibonacci.h + ${include_path}/CTFibonacci.inl ${include_path}/Fibonacci.h ) @@ -90,6 +93,10 @@ generate_export_header(${target} EXPORT_FILE_NAME ${export_file} EXPORT_MACRO_NAME ${export_macro} ) +generate_template_export_header(${target} + ${target_id} + ${template_export_file} +) # diff --git a/source/fiblib/include/fiblib/CTFibonacci.h b/source/fiblib/include/fiblib/CTFibonacci.h new file mode 100644 index 0000000..4b9d2d5 --- /dev/null +++ b/source/fiblib/include/fiblib/CTFibonacci.h @@ -0,0 +1,29 @@ + +#pragma once + + +#include + + +namespace fiblib +{ + + +/** +* @brief +* Compile-time computation of fibonacci numbers +*/ +template +class FIBLIB_TEMPLATE_API CTFibonacci +{ +public: + enum { + value = CTFibonacci::value + CTFibonacci::value + }; +}; + + +} // namespace fiblib + + +#include diff --git a/source/fiblib/include/fiblib/CTFibonacci.inl b/source/fiblib/include/fiblib/CTFibonacci.inl new file mode 100644 index 0000000..900a789 --- /dev/null +++ b/source/fiblib/include/fiblib/CTFibonacci.inl @@ -0,0 +1,28 @@ + +#pragma once + + +namespace fiblib +{ + + +template <> +class FIBLIB_TEMPLATE_API CTFibonacci<0> +{ +public: + enum { + value = 0 + }; +}; + +template <> +class FIBLIB_TEMPLATE_API CTFibonacci<1> +{ +public: + enum { + value = 1 + }; +}; + + +} // namespace fiblib From f9021323d571184d8dfdaa4f2f78125dc59c3c56 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Thu, 13 Apr 2017 15:58:44 +0200 Subject: [PATCH 2/2] Remove unused macro definition for _TEMPLATE_NO_EXPORT --- source/codegeneration/template_api.h.in | 1 - source/codegeneration/template_msvc_api.in | 1 - 2 files changed, 2 deletions(-) diff --git a/source/codegeneration/template_api.h.in b/source/codegeneration/template_api.h.in index 1564245..28b7bd2 100644 --- a/source/codegeneration/template_api.h.in +++ b/source/codegeneration/template_api.h.in @@ -6,7 +6,6 @@ #ifdef ${target_id}_STATIC_DEFINE # define ${target_id}_TEMPLATE_API -# define ${target_id}_TEMPLATE_NO_EXPORT #else # ifndef ${target_id}_TEMPLATE_API # ifdef ${target}_EXPORTS diff --git a/source/codegeneration/template_msvc_api.in b/source/codegeneration/template_msvc_api.in index 834dfda..e9078e9 100644 --- a/source/codegeneration/template_msvc_api.in +++ b/source/codegeneration/template_msvc_api.in @@ -6,7 +6,6 @@ #ifdef ${target_id}_STATIC_DEFINE # define ${target_id}_TEMPLATE_API -# define ${target_id}_TEMPLATE_NO_EXPORT #else # ifndef ${target_id}_TEMPLATE_API # ifdef ${target}_EXPORTS